一、概述
整合 Spring、SpringMVC、MyBatis。
二、整合步骤
2.1、pom
<dependencies>
<!-- 普通maven项目中使用Sl4j注解 -->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.22</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>1.7.32</version>
</dependency>
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
<version>1.2.10</version>
</dependency>
<!-- 工具 -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.76</version>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-collections4</artifactId>
<version>4.3</version>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<version>3.11</version>
</dependency>
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-all</artifactId>
<version>5.7.22</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.12.1</version>
</dependency>
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-web</artifactId>
<version>2.12.1</version>
</dependency>
<!-- 三大框架整合 -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>5.3.4</version>
</dependency>
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.5.6</version>
</dependency>
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis-spring</artifactId>
<version>2.0.6</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.26</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>5.3.4</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aop</artifactId>
<version>5.3.4</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-beans</artifactId>
<version>5.3.4</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.3.4</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>5.3.4</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-expression</artifactId>
<version>5.3.4</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-tx</artifactId>
<version>5.3.4</version>
</dependency>
<!-- 动态代理 -->
<dependency>
<groupId>cglib</groupId>
<artifactId>cglib</artifactId>
<version>3.1</version>
</dependency>
<dependency>
<groupId>aopalliance</groupId>
<artifactId>aopalliance</artifactId>
<version>1.0</version>
</dependency>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.9.19</version>
</dependency>
</dependencies>
<build>
<!--
说明:
在maven中,默认情况下maven要求我们将xxxMapper.xml配置文件、properties配置等都放在resources目录下,如果我们强行放在java目录,
默认情况下打包的时候这个配置文件将会被自动忽略掉。
场景一:将xxxMapper.xml文件和xxxMapper接口放在同一个包下
解决方法:在resources目录添加下边的配置
场景二:将xxxMapper.xml文件放在resources目录
解决方法:在resources目录创建和xxxMapper同样的Directory
坑:注意创建的是Directory,不是package
-->
<resources>
<resource>
<directory>src/main/java</directory>
<includes>
<include>**/*.xml</include>
</includes>
</resource>
<resource>
<directory>src/main/resources</directory>
</resource>
</resources>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.10.1</version>
<configuration>
<source>8</source>
<target>8</target>
</configuration>
</plugin>
</plugins>
</build>
2.2、db.properties
db.driver=com.mysql.cj.jdbc.Driver
db.url=jdbc:mysql://localhost:3306/20231106_ssm?useSSL=false&useUnicode=true&characterEncoding=UTF8&serverTimezone=GMT
db.username=root
db.password=123456
2.3、init.sql
drop DATABASE if EXISTS 20231106_ssm;
create DATABASE 20231106_ssm;
use 20231106_ssm;
CREATE TABLE `user` (
`id` int NOT NULL AUTO_INCREMENT COMMENT '主键',
`username` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '用户名',
`password` varchar(60) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '密码',
`age` int NULL DEFAULT NULL COMMENT '年龄',
PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_0900_ai_ci ROW_FORMAT = Dynamic;
INSERT INTO `user` VALUES (1, 'zhangsan', 'zhangsan123', 23);
INSERT INTO `user` VALUES (2, 'lisi', 'lisi123', 24);
2.4、applicationContext.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd http://www.springframework.org/schema/aop https://www.springframework.org/schema/aop/spring-aop.xsd">
<context:property-placeholder location="classpath:db.properties"/>
<context:component-scan base-package="org.star" use-default-filters="true">
<context:exclude-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
</context:component-scan>
<bean class="org.springframework.jdbc.datasource.DriverManagerDataSource" id="dataSource">
<property name="driverClassName" value="${db.driver}"/>
<property name="url" value="${db.url}"/>
<property name="username" value="${db.username}"/>
<property name="password" value="${db.password}"/>
</bean>
<bean class="org.mybatis.spring.SqlSessionFactoryBean" id="sqlSessionFactoryBean">
<property name="dataSource" ref="dataSource"/>
<property name="typeAliasesPackage" value="org.star.entity.model"/>
<property name="configuration">
<bean class="org.apache.ibatis.session.Configuration">
<property name="logImpl" value="org.apache.ibatis.logging.stdout.StdOutImpl"></property>
<property name="cacheEnabled" value="true"></property>
</bean>
</property>
<property name="mapperLocations" value="classpath:mappers/*.xml"/>
<!--
<property name="mapperLocations">
<list>
<value>classpath*:org/star/mapper/*.xml</value>
</list>
</property>
-->
</bean>
<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer" id="mapperScannerConfigurer">
<property name="sqlSessionFactoryBeanName" value="sqlSessionFactoryBean"/>
<property name="basePackage" value="org.star.mapper"/>
</bean>
<!-- 事务管理器 -->
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"></property>
</bean>
<!--
声明式事务:spring中的事务是基于aop实现,但使用的不是通知而是拦截器
-->
<tx:advice id="txAdvice" transaction-manager="transactionManager">
<!--
定义事务的对象信息
-->
<tx:attributes>
<!--
disable*:表示以disable开头的所有方法
-->
<tx:method name="*" propagation="REQUIRED" isolation="DEFAULT"/>
</tx:attributes>
</tx:advice>
<aop:config>
<aop:pointcut id="txPointCut" expression="execution(* org.star.service.UserService.*(..))"/>
<aop:advisor advice-ref="txAdvice" pointcut-ref="txPointCut"></aop:advisor>
</aop:config>
</beans>
2.5、dispatcherServlet.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/mvc https://www.springframework.org/schema/mvc/spring-mvc.xsd">
<context:component-scan base-package="org.star" use-default-filters="false">
<context:include-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
</context:component-scan>
<mvc:annotation-driven/>
</beans>
2.6、web.xml
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
version="4.0">
<!-- spring配置信息 -->
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:applicationContext.xml</param-value>
</context-param>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<!-- springmvc配置信息 -->
<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:dispatcherServlet.xml</param-value>
</init-param>
</servlet>
<servlet-mapping>
<servlet-name>springmvc</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
<!-- 全局乱码过滤器配置 -->
<filter>
<filter-name>encodingFilter</filter-name>
<filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
<init-param>
<param-name>encoding</param-name>
<param-value>UTF-8</param-value>
</init-param>
<init-param>
<param-name>forceRequestEncoding</param-name>
<param-value>true</param-value>
</init-param>
<init-param>
<param-name>forceResponseEncoding</param-name>
<param-value>true</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>encodingFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
</web-app>
2.7、UserDO
/**
* @Author : 一叶浮萍归大海
* @Date: 2023/11/6 11:34
* @Description:
*/
@Data
@AllArgsConstructor
@NoArgsConstructor
@Accessors(chain = true)
@ToString(callSuper = true)
public class UserDO implements Serializable {
/**
* 编号
*/
private Integer id;
/**
* 用户名
*/
private String username;
/**
* 密码
*/
private String password;
/**
* 年龄
*/
private Integer age;
}
2.8、UserMappper
/**
* @Author : 一叶浮萍归大海
* @Date: 2023/11/6 11:35
* @Description:
*/
public interface UserMapper {
/**
* 添加用户
* @param param
*/
void saveUser(UserDO param);
/**
* 查询所有的用户
* @return
*/
List<UserDO> listAllUser();
/**
* 根据id查询用户
* @param id
* @return
*/
UserDO getUserById(Integer id);
}
2.9、UserMapper.xml
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="org.star.mapper.UserMapper">
<insert id="saveUser">
insert into `user`(username,password,age) values (#{username},#{password},#{age})
</insert>
<select id="listAllUser" resultType="userDO">
select * from `user`
</select>
<select id="getUserById" resultType="userDO">
select * from `user` where id = #{id}
</select>
</mapper>
2.10、UserService
/**
* @Author : 一叶浮萍归大海
* @Date: 2023/11/6 11:36
* @Description:
*/
@Service
public class UserService {
@Autowired
private UserMapper userMapper;
@Transactional(propagation = Propagation.REQUIRED,rollbackFor = Exception.class)
public List<UserDO> listAllUser() {
return userMapper.listAllUser();
}
public void saveUser(UserDO param) {
userMapper.saveUser(param);
}
/**
* 不加此注解的话,将会执行多次数据库查询
* 参考:https://blog.51cto.com/u_15942107/6019692
* @param id
* @return
*/
@Transactional(propagation = Propagation.REQUIRED,rollbackFor = Exception.class)
public UserDO getUserById(Integer id) {
UserDO u1 = userMapper.getUserById(id);
UserDO u2 = userMapper.getUserById(id);
UserDO u3 = userMapper.getUserById(id);
System.out.println(u1);
System.out.println(u2);
System.out.println(u3);
return userMapper.getUserById(id);
}
}
2.11、UserController
@Slf4j
@RestController
public class UserController {
@Autowired
private UserService userService;
@PostMapping("/saveUser")
public String saveUser(@RequestBody UserDO param) {
log.info("UserController saveUser param:{}", param);
userService.saveUser(param);
return "SUCCESS";
}
@GetMapping("/listAllUser")
public List<UserDO> listAllUser() {
log.info("=================>listAllUser");
return userService.listAllUser();
}
@GetMapping("/getUserById/{id}")
public UserDO getUserById(@PathVariable("id") Integer id) {
log.info("=================>getUserById id:{}",id);
return userService.getUserById(id);
}
}
三、测试
http://localhost:8080/listAllUser