前面已经把Mybatis
、Spring
和SpringMVC
三个框架进行了介绍,今天主要介绍的就是把这三个框架整合在一起完成我们的业务功能开发,具体如何来整合,我们一步步来介绍。
1. 流程分析
(1) 创建工程
- 创建一个Maven的web工程
- pom.xml添加SSM需要的依赖jar包
- 编写Web项目的入口配置类,实现
AbstractAnnotationConfigDispatcherServletInitializer
重写以下方法- getRootConfigClasses() :返回Spring的配置类->需要SpringConfig配置类
- getServletConfigClasses() :返回SpringMVC的配置类->需要SpringMvcConfig配置类
- getServletMappings() : 设置SpringMVC请求拦截路径规则
- getServletFilters() :设置过滤器,解决POST请求中文乱码问题
(2)SSM整合[重点是各个配置的编写]
- SpringConfig
- 标识该类为配置类 @Configuration
- 扫描Service所在的包 @ComponentScan
- 在Service层要管理事务 @EnableTransactionManagement
- 读取外部的properties配置文件 @PropertySource
- 整合Mybatis需要引入Mybatis相关配置类 @Import
- 第三方数据源配置类 JdbcConfig
- 构建DataSource数据源,DruidDataSouroce,需要注入数据库连接四要素, @Bean @Value
- 构建平台事务管理器,DataSourceTransactionManager,@Bean
- Mybatis配置类 MybatisConfig
- 构建SqlSessionFactoryBean并设置别名扫描与数据源,@Bean
- 构建MapperScannerConfigurer并设置DAO层的包扫描
- 第三方数据源配置类 JdbcConfig
- SpringMvcConfig
- 标识该类为配置类 @Configuration
- 扫描Controller所在的包 @ComponentScan
- 开启SpringMVC注解支持 @EnableWebMvc
(3)功能模块[与具体的业务模块有关]
- 创建数据库表
- 根据数据库表创建对应的模型类
- 通过Dao层完成数据库表的增删改查(接口+自动代理)
- 编写Service层[Service接口+实现类]
- @Service
- @Transactional
- 整合Junit对业务层进行单元测试
- @RunWith
- @ContextConfiguration
- @Test
- 编写Controller层
- 接收请求 @RequestMapping @GetMapping @PostMapping @PutMapping @DeleteMapping
- 接收数据 简单、POJO、嵌套POJO、集合、数组、JSON数据类型
- @RequestParam
- @PathVariable
- @RequestBody
- 转发业务层
- @Autowired
- 响应结果
- @ResponseBody
2. 整合配置
接下来,我们就可以按照上述的步骤一步步的来完成SSM的整合。
步骤1:创建Maven的web项目
可以使用Maven的骨架创建
步骤2:添加依赖
pom.xml添加SSM所需要的依赖jar包
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.dcxuexi</groupId>
<artifactId>springmvc_06_ssm</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>war</packaging>
<name>springmvc_06_ssm Maven Webapp</name>
<!-- FIXME change it to the project's website -->
<url>http://www.example.com</url>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.source>1.8</maven.compiler.source>
<maven.compiler.target>1.8</maven.compiler.target>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>5.2.15.RELEASE</version>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>3.1.0</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>5.2.12.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
<version>5.2.15.RELEASE</version>
</dependency>
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.5.10</version>
</dependency>
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis-spring</artifactId>
<version>2.0.7</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.30</version>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.2.11</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.13.2</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.9.8</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.tomcat.maven</groupId>
<artifactId>tomcat7-maven-plugin</artifactId>
<version>2.1</version>
<configuration>
<port>80</port>
<path>/springmvc</path>
<uriEncoding>UTF-8</uriEncoding>
</configuration>
</plugin>
</plugins>
</build>
</project>
步骤3:创建项目包结构
- config目录存放的是相关的配置类
- controller编写的是Controller类
- dao存放的是Dao接口,因为使用的是Mapper接口代理方式,所以没有实现类包
- service存的是Service接口,impl存放的是Service实现类
- resources:存入的是配置文件,如Jdbc.properties
- webapp:目录可以存放静态资源
- test/java:存放的是测试类
步骤4:创建SpringConfig配置类
@Configuration
@ComponentScan("com.dcxuexi.service")
@PropertySource("classpath:jdbc.properties")
@Import({JdbcConfig.class,MyBatisConfig.class})
@EnableTransactionManagement
public class SpringConfig {
}
步骤5:创建JdbcConfig配置类
public class JdbcConfig {
@Value("${jdbc.driver}")
private String driver;
@Value("${jdbc.url}")
private String url;
@Value("${jdbc.username}")
private String username;
@Value("${jdbc.password}")
private String password;
@Bean
public DataSource dataSource(){
DruidDataSource dataSource = new DruidDataSource();
dataSource.setDriverClassName(driver);
dataSource.setUrl(url);
dataSource.setUsername(username);
dataSource.setPassword(password);
return dataSource;
}
@Bean
public PlatformTransactionManager platformTransactionManager(DataSource dataSource){
DataSourceTransactionManager dataSourceTransactionManager = new DataSourceTransactionManager();
dataSourceTransactionManager.setDataSource(dataSource);
return dataSourceTransactionManager;
}
}
步骤6:创建MybatisConfig配置类
public class MyBatisConfig {
@Bean
public SqlSessionFactoryBean sqlSessionFactoryBean(DataSource dataSource){
SqlSessionFactoryBean sqlSessionFactoryBean = new SqlSessionFactoryBean();
sqlSessionFactoryBean.setDataSource(dataSource);
sqlSessionFactoryBean.setTypeAliasesPackage("com.dcxuexi.domain");
return sqlSessionFactoryBean;
}
@Bean
public MapperScannerConfigurer mapperScannerConfigurer(){
MapperScannerConfigurer mapperScannerConfigurer = new MapperScannerConfigurer();
mapperScannerConfigurer.setBasePackage("com.dcxuexi.dao");
return mapperScannerConfigurer;
}
}
步骤7:创建jdbc.properties
在resources下提供jdbc.properties,设置数据库连接四要素
jdbc.driver=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/mybatis
jdbc.username=root
jdbc.password=root
步骤8:创建SpringMVC配置类
@Configuration
@ComponentScan("com.dcxuexi.controller")
@EnableWebMvc
public class SpringMvcConfig {
}
步骤9:创建Web项目入口配置类
public class ServletConfig extends AbstractAnnotationConfigDispatcherServletInitializer {
//加载Spring配置类
@Override
protected Class<?>[] getRootConfigClasses() {
return new Class[]{SpringConfig.class};
}
//加载SpringMVC配置类
@Override
protected Class<?>[] getServletConfigClasses() {
return new Class[]{SpringMvcConfig.class};
}
//设置SpringMVC请求地址拦截规则
@Override
protected String[] getServletMappings() {
return new String[]{"/"};
}
//设置post请求中文乱码过滤器
@Override
protected Filter[] getServletFilters() {
CharacterEncodingFilter characterEncodingFilter = new CharacterEncodingFilter();
characterEncodingFilter.setEncoding("UTF-8");
return new Filter[]{characterEncodingFilter};
}
}
至此SSM整合的环境就已经搭建好了。在这个环境上,我们如何进行功能模块的开发呢?
3. 功能模块开发
需求:对表platform_user进行新增、修改、删除、根据user_id查询和查询所有
步骤1:创建数据库及表
CREATE TABLE `platform_user` (
`user_id` mediumint(8) unsigned NOT NULL AUTO_INCREMENT,
`email` varchar(60) NOT NULL DEFAULT '',
`user_name` varchar(60) NOT NULL DEFAULT '',
`branch_name` varchar(30) DEFAULT NULL,
PRIMARY KEY (`user_id`) USING BTREE,
KEY `idx_platform_user_id_name` (`user_name`) USING BTREE,
KEY `idx_platform_user_email` (`email`) USING BTREE
) ENGINE=InnoDB AUTO_INCREMENT=146 DEFAULT CHARSET=utf8;
步骤2:编写模型类
public class User implements Serializable {
private Integer userId;
private String userName;
private String email;
private String branchName;
public Integer getUserId() {
return userId;
}
public void setUserId(Integer userId) {
this.userId = userId;
}
public String getUserName() {
return userName;
}
public void setUserName(String userName) {
this.userName = userName;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
public String getBranceName() {
return branchName;
}
public void setBranceName(String branceName) {
this.branchName = branceName;
}
@Override
public String toString() {
return "User{" +
"userId=" + userId +
", userName='" + userName + '\'' +
", email='" + email + '\'' +
", branchName='" + branchName + '\'' +
'}';
}
}
步骤3:编写Dao接口
public interface UserDao {
@Insert("insert into platform_user (email,user_name,branch_name) values (#{email},#{userName},#{branchName})")
public Boolean save(User user);
@Update("update platform_user set email = #{email}, user_name=#{userName}, branch_name=#{branchName} where user_id = #{userId}")
public Boolean update(User user);
@Delete("delete from platform_user where user_id = #{userId}")
public Boolean delete(Integer userId);
@Select("select user_id as userId, email, user_name as userName, branch_name as branchName from platform_user where user_id = #{userId}")
public User findByUserId(Integer userId);
@Select("select user_id as userId, email, user_name as userName, branch_name as branchName from platform_user")
public List<User> findAll();
}
步骤4:编写Service接口和实现类
@Transactional
public interface UserService {
/**
* @Author DongChuang
* @Description //保存
* @Date 2022/11/7 22:15
* @Param
* @param user
* @return
* @return java.lang.Boolean
*/
public Boolean save(User user);
/**
* @Author DongChuang
* @Description //根据userId修改
* @Date 2022/11/7 22:15
* @Param
* @param user
* @return
* @return java.lang.Boolean
*/
public Boolean update(User user);
/**
* @Author DongChuang
* @Description //根据userId 删除
* @Date 2022/11/7 22:16
* @Param
* @param userId
* @return
* @return java.lang.Boolean
*/
public Boolean delete(Integer userId);
/**
* @Author DongChuang
* @Description //根据userId 查询
* @Date 2022/11/7 22:16
* @Param
* @param userId
* @return
* @return com.dcxuexi.domain.User
*/
public User findByUserId(Integer userId);
/*/**
* @Author DongChuang
* @Description //查询所有
* @Date 2022/11/7 22:17
* @Param
* @return
* @return java.util.List<com.dcxuexi.domain.User>
*/
public List<User> findAll();
}
@Service
public class UserServiceImpl implements UserService {
@Autowired
private UserDao userDao;
@Override
public Boolean save(User user) {
try {
Boolean res = userDao.save(user);
return res;
}catch (Exception e){
return false;
}
}
@Override
public Boolean update(User user) {
try {
Boolean res = userDao.update(user);
return res;
}catch (Exception e){
return false;
}
}
@Override
public Boolean delete(Integer userId) {
try {
Boolean res = userDao.delete(userId);
return res;
}catch (Exception e){
return false;
}
}
@Override
public User findByUserId(Integer userId) {
return userDao.findByUserId(userId);
}
@Override
public List<User> findAll() {
return userDao.findAll();
}
}
说明:
-
userDao在Service中注入的会提示一个红线提示,为什么呢?
- UserDao是一个接口,没有实现类,接口是不能创建对象的,所以最终注入的应该是代理对象
- 代理对象是由Spring的IOC容器来创建管理的
- IOC容器又是在Web服务器启动的时候才会创建
- IDEA在检测依赖关系的时候,没有找到适合的类注入,所以会提示错误提示
- 但是程序运行的时候,代理对象就会被创建,框架会使用DI进行注入,所以程序运行无影响。
-
如何解决上述问题?
-
可以不用理会,因为运行是正常的
-
设置错误提示级别
-
步骤5:编写Contorller类
@RestController
@RequestMapping("/user")
public class UserController {
@Autowired
private UserService userService;
@PostMapping
public Boolean save(@RequestBody User user){
return userService.save(user);
}
@PutMapping
public Boolean update(@RequestBody User user){
return userService.update(user);
}
@DeleteMapping("/{#id}")
public Boolean delete(@PathVariable("id") Integer userId){
return userService.delete(userId);
}
@GetMapping("/{#id}")
public User findByUserId(@PathVariable("id") Integer userId){
return userService.findByUserId(userId);
}
@GetMapping
public List<User> findAll(){
return userService.findAll();
}
}
对于用户模块的增删改查就已经完成了编写,我们可以从后往前写也可以从前往后写,最终只需要能把功能实现即可。
接下来我们就先把业务层的代码使用Spring整合Junit
的知识点进行单元测试:
4. 单元测试
步骤1:新建测试类
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = SpringConfig.class)
public class UserServiceTest {
}
步骤2:注入Service类
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = SpringConfig.class)
public class UserServiceTest {
@Autowired
private UserService userService;
}
步骤3:编写测试方法
我们先来对查询进行单元测试。
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = SpringConfig.class)
public class UserServiceTest {
@Autowired
private UserService userService;
@Test
public void findByUserId(){
User user = userService.findByUserId(10);
System.out.println(user);
}
@Test
public void findAll(){
List<User> userList = userService.findAll();
userList.forEach(System.out::println);
}
}
根据userId查询,测试的结果为:
查询所有,测试的结果为:
5. PostMan测试
新增
http://localhost/springmvc/user
{
"userName": "hljmdkja",
"email": "hljmdkja@foxmail.com",
"branceName": "黑龙江省明迪科技开发有限公司2"
}
修改
http://localhost/springmvc/user
{
"userId": 146,
"userName": "hljmdkja12138",
"email": "hljmdkja12138@foxmail.com",
"branceName": "黑龙江省明迪科技开发有限公司12138"
}
删除
http://localhost/springmvc/user/129
查询单个
http://localhost/springmvc/user/10
查询所有
http://localhost/springmvc/user