<dependencies>
<!-- Spring MVC -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>4.3.2.RELEASE</version>
</dependency>
<!-- MyBatis -->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis-spring</artifactId>
<version>1.3.0</version>
</dependency>
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.4.1</version>
</dependency>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.9.0.BETA-1</version>
</dependency>
<!-- Spring 支援 -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context-support</artifactId>
<version>4.3.0.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>4.2.5.RELEASE</version>
</dependency>
<!-- 資料庫連線池 Druid -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.0.26</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.25</version>
</dependency>
<!-- Web 相關 -->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>3.0.1</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>javax.servlet.jsp</groupId>
<artifactId>jsp-api</artifactId>
<version>2.2</version>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>jstl</artifactId>
<version>1.2</version>
</dependency>
<!-- 工具庫 -->
<dependency>
<groupId>commons-logging</groupId>
<artifactId>commons-logging</artifactId>
<version>1.2</version>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-fileupload</artifactId>
<version>1.3.3</version>
</dependency>
</dependencies>
<web-app>
<!-- Spring 容器啟動 -->
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:spring-mybatis.xml</param-value>
</context-param>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<!-- Spring MVC DispatcherServlet -->
<servlet>
<servlet-name>springmvc</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:spring-mvc.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
<async-supported>true</async-supported>
</servlet>
<servlet-mapping>
<servlet-name>springmvc</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
</web-app>
<beans xmlns="https://www.springframework.org/schema/beans"
xmlns:xsi="https://www.w3.org/2001/XMLSchema-instance"
xmlns:context="https://www.springframework.org/schema/context"
xmlns:mvc="https://www.springframework.org/schema/mvc"
xsi:schemaLocation="...">
<!-- 掃描 Controller -->
<context:component-scan base-package="com.xxx">
<context:include-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
<context:include-filter type="annotation" expression="org.springframework.web.bind.annotation.ControllerAdvice"/>
</context:component-scan>
<!-- 註解驅動 -->
<mvc:annotation-driven />
<!-- 靜態資源處理 (配合 url-pattern: /) -->
<mvc:default-servlet-handler />
<mvc:resources mapping="/static/**" location="/static/" />
<!-- 視圖解析器 -->
<bean id="defaultViewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver" p:order="1">
<property name="viewClass" value="org.springframework.web.servlet.view.JstlView"/>
<property name="contentType" value="text/html"/>
<property name="prefix" value=""/>
<property name="suffix" value=".jsp"/>
</bean>
<!-- 異常處理 -->
<bean id="exceptionHandlerExceptionResolver" class="org.springframework.web.servlet.mvc.method.annotation.ExceptionHandlerExceptionResolver"/>
<!-- 檔案上傳 -->
<bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
<property name="defaultEncoding" value="UTF-8"/>
</bean>
</beans>
<beans xmlns="https://www.springframework.org/schema/beans"
xmlns:xsi="https://www.w3.org/2001/XMLSchema-instance"
xmlns:aop="https://www.springframework.org/schema/aop"
xmlns:tx="https://www.springframework.org/schema/tx"
xmlns:context="https://www.springframework.org/schema/context"
xsi:schemaLocation="...">
<!-- Druid 資料源 -->
<bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource" init-method="init" destroy-method="close">
<property name="url" value="jdbc:mysql://127.0.0.1:3306/springtest"/>
<property name="username" value="root"/>
<property name="password" value="123456"/>
</bean>
<!-- 事務管理器 -->
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"/>
</bean>
<!-- SqlSessionFactory -->
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<property name="dataSource" ref="dataSource"/>
<property name="mapperLocations" value="classpath:com/xxx/**/mapper/*.xml"/>
</bean>
<!-- Mapper 掃描器 -->
<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
<property name="basePackage" value="com.xxx"/>
<property name="markerInterface" value="com.xxx.MybatisMapper"/>
</bean>
<!-- 事務通知 -->
<tx:advice id="txAdvice" transaction-manager="transactionManager">
<tx:attributes>
<tx:method name="get*" propagation="SUPPORTS" read-only="true"/>
<tx:method name="find*" propagation="SUPPORTS" read-only="true"/>
<tx:method name="list*" propagation="SUPPORTS" read-only="true"/>
<tx:method name="*" propagation="REQUIRED" rollback-for="java.lang.Exception"/>
</tx:attributes>
</tx:advice>
<!-- AOP 事務切面 -->
<aop:config expose-proxy="true" proxy-target-class="true">
<aop:pointcut id="txPointcut" expression="execution(* com.xxx.*..service..*+.*(..))"/>
<aop:advisor id="txAdvisor" advice-ref="txAdvice" pointcut-ref="txPointcut"/>
</aop:config>
</beans>
spring-mybatis.xmlspring-mvc.xml<!-- 模式一:標記介面 (推薦,精確控制) -->
<property name="markerInterface" value="com.xxx.MybatisMapper"/>
<!-- 模式二:掃描所有介面 (簡單但可能掃描過多) -->
<property name="basePackage" value="com.xxx.mapper"/>
| 方法前綴 | 傳播行為 | 唯讀 | 適用場景 |
|---|---|---|---|
| get/find/list* | SUPPORTS | true | 單次查詢、多表聯查只讀 |
| save/update/delete/insert* | REQUIRED | false | 寫操作、需事務保證 |
| 其他 * | REQUIRED | false | 預設寫操作 |
mapperLocations 路徑、命名空間對應、介面方法簽名proxy-target-class="true" (CGLIB 代理)、Service 類非 final、方法非 privatecharacterEncoding=utf8@Configuration
@EnableWebMvc
@ComponentScan(basePackages = "com.xxx", includeFilters = @Filter(Controller.class))
@EnableTransactionManagement
@MapperScan(basePackages = "com.xxx.mapper", markerInterface = MybatisMapper.class)
public class AppConfig extends WebMvcConfigurerAdapter {
@Bean public DataSource dataSource() { ... }
@Bean public SqlSessionFactoryBean sqlSessionFactory() { ... }
@Bean public DataSourceTransactionManager transactionManager() { ... }
@Bean public InternalResourceViewResolver viewResolver() { ... }
}
SpringMVC + MyBatis 整合核心在於:**雙容器分層、SqlSessionFactory 整合 DataSource、Mapper 掃描、AOP 宣告式事務**。掌握 XML 配置原理後,可平滑遷移至 Spring Boot 自動配置 (@SpringBootApplication + mybatis-spring-boot-starter) 享受零配置開發體驗。