一. 配置准备
1.1 module结构
SSM整合即整合 Spring+SpringMVC+MyBatis;
需要配置的有JDBC、MyBatis、Spring核心配置、SpringMVC配置和 容器启动配置;
1.2 pom.xml
导入jar包;
Tomcat、spring、spring-jdbc、spring-webmvc、servlet、mybatis、德鲁伊、jaskon等
<?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.abc</groupId>
<artifactId>SSM_2</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>war</packaging>
<name>SSM_2 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>8</maven.compiler.source>
<maven.compiler.target>8</maven.compiler.target>
</properties>
<!-- Tomcat 7 -->
<build>
<plugins>
<plugin>
<groupId>org.apache.tomcat.maven</groupId>
<artifactId>tomcat7-maven-plugin</artifactId>
<version>2.2</version>
<configuration>
<port>8088</port> <!-- 设置端口号-->
<path>/</path> <!-- 项目访问路径 -->
</configuration>
</plugin></plugins>
</build>
<dependencies>
<!--servlet -->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>3.1.0</version>
<scope>provided</scope>
</dependency>
<!--Spring-->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>5.2.10.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
<version>5.2.10.RELEASE</version>
</dependency>
<!--数据库修改操作都要导入 -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>5.2.10.RELEASE</version>
</dependency>
<!-- Spring整合mybatis -->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis-spring</artifactId>
<version>1.3.0</version>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.1.16</version>
</dependency>
<!-- 数据库连接池 -->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.5.5</version>
</dependency>
<!--json序列化工具 -->
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.9.0</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
<version>5.2.10.RELEASE</version>
</dependency>
<!-- 连接mysql -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.20</version>
</dependency>
<!-- 测试Junit -->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<!-- <scope>test</scope> -->
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>1.7.20</version>
<!-- <scope>test</scope> -->
</dependency>
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
<version>1.2.3</version>
<!-- <scope>test</scope> -->
</dependency>
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-core</artifactId>
<version>1.2.3</version>
<!-- <scope>test</scope> -->
</dependency>
</dependencies>
</project>
1.3 resources
1.3.1 jdbc.properties:
jdbc.driver=com.mysql.cj.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/bjpowernode
jdbc.username=root
jdbc.password=123456
1.4 config
1.4.1 SpringConfig:
@Configuration
@ComponentScan("com.abc.service")
@PropertySource("classpath:jdbc.properties")
@Import({JdbcConfig.class,MybatisConfig.class})
public class SpringConfig {
}
1.4.2 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;
}
}
1.4.3 MybatisConfig:
public class MybatisConfig {
// 数据源
@Bean
public SqlSessionFactoryBean sqlSessionFactory(DataSource dataSource){
SqlSessionFactoryBean factoryBean = new SqlSessionFactoryBean();
factoryBean.setDataSource(dataSource);
factoryBean.setTypeAliasesPackage("com.abc.pojo");
return factoryBean;
}
// 扫描映射文件mapper
@Bean
public MapperScannerConfigurer mapperScannerConfigurer(){
MapperScannerConfigurer msc = new MapperScannerConfigurer();
msc.setBasePackage("com.abc.dao");
return msc;
}
}
1.4.4 SpringMvcConfig:
@Configuration
@ComponentScan("com.abc.controller")
@EnableWebMvc // 功能多,涉及格式转换,json序列化等
public class SpringMvcConfig {
}
1.4.5 ServletInitializer Servlet启动的配置类:★
// 定义一个servlet容器启动的配置类,在里面加载Spring的配置
public class ServletInitializer extends AbstractDispatcherServletInitializer {
// 加载SpringMVC的IOC容器配置
@Override
protected WebApplicationContext createServletApplicationContext() {
AnnotationConfigWebApplicationContext ctx=new AnnotationConfigWebApplicationContext();
ctx.register(SpringMvcConfig.class); // 使用定义的SpringMvc配置文件
return ctx;
}
//加载spring容器的配置
@Override
protected WebApplicationContext createRootApplicationContext() {
AnnotationConfigWebApplicationContext ctx=new AnnotationConfigWebApplicationContext();
ctx.register(SpringConfig.class); // 使用定义的Spring配置文件
return ctx;
}
//设置哪些请求归属SpringMVC处理
@Override
protected String[] getServletMappings() {
return new String[]{"/"}; //所有请求归SrpingMvc处理
}
//设置post请求中文乱码过滤器
@Override
protected Filter[] getServletFilters() {
CharacterEncodingFilter filter = new CharacterEncodingFilter();
filter.setEncoding("utf-8");
return new Filter[]{filter};
}
}
注意:
1 .容器初始化配置类中,当web容器加载时,会加载SpringMvcConfig和SpringConfig,分别加载各自的配置类;
这两个配置类造出来的容器对象不是同一个! 但是SpringMVC的容器能访问Spring的容器,Spring容器不能访问SpringMVC的容器!(父子容器)
二. 功能模块
完整目录:
即需要让设置的配置能够控制模块;
2.1 建库建表
建立book表,简单不多说;
2.2 pojo层
对应表结构建立pojo实体类;
2.2.1 Book类:
注意pojo实体类属性名称=数据库表中的字段名;
public class Book {
private Integer id;
private Integer type;
private String name;
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public Integer getType() {
return type;
}
public void setType(Integer type) {
this.type = type;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public String toString() {
return "book{" +
"id=" + id +
", type=" + type +
", name='" + name + '\'' +
'}';
}
}
2.3 dao 层
2.3.1 BookDao 代理接口:
提供增删改查功能,此处使用了mapper的xml映射文件进行MyBatis开发;
//代理接口
public interface BookDao {
public void save(Book book); // 增
public void delete(Integer id); // 删
public void update(Book book); // 改
public Book getById(Integer id); // 查
public List<Book> selectAll(); // 查全部
}
2.4 resources.com.abc.dao
2.4.1 BookDao.xml 映射文件
mapper映射文件在和BookDao同名的文件夹内;
注意:
- 抽象方法中的参数占位符要和pojo实体类中的属性名称要保持一致;
- 文件夹是三层目录,而不是文件夹名为“com.abc.dao”,否则报错:
org.apache.ibatis.binding.BindingException: Invalid bound statement (not found.....
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<!-- namespace 名称空间 是.java接口文件 的全路径名! -->
<mapper namespace="com.abc.dao.BookDao">
<!-- resultMap-->
<!-- <resultMap id="testkRM" type="com.abc.testk">-->
<!-- <id column="id" property="id"/></resultMap>-->
<!-- <result column="name" property="nameJava"/></resultMap>-->
<select id="save" resultType="com.abc.pojo.Book">
insert into Book(id,type,name) values(#{id},#{type}),#{name});
</select>
<select id="delete" resultType="com.abc.pojo.Book">
delete from Book where id=#{id};
</select>
<select id="update" resultType="com.abc.pojo.Book">
update Book set type=#{type},name=#{name};
</select>
<select id="getById" resultType="com.abc.pojo.Book">
select * from book where id=#{id};
</select>
<select id="selectAll" resultType="com.abc.pojo.Book">
select * from book;
</select>
</mapper>
2.5 service层
2.5.1 BookService抽象类:
public interface BookService {
public boolean save(Book book); // 增
public boolean delete(Integer id); // 删
public boolean update(Book book); // 改
public Book getById(Integer id); // 查
public List<Book> selectAll(); // 查全部
}
2.5.2 impl
BookServiceImpl:
需要使用dao层的对象来增删改查,所以需要bean自动注入-----创建BookDao成员变量, 并添加注解 @Service @Autowird
对于增删改的返回值,不是void,而是boolean;
@Service
public class BookServiceImpl implements BookService {
// 需要自动注入BookDao的bean
@Autowired
private BookDao bookDao;
public boolean save(Book book){
bookDao.save(book);
return true;
}; // 增
public boolean delete(Integer id){
bookDao.delete(id);
return true;
}; // 删
public boolean update(Book book){
bookDao.update(book);
return true;
}; // 改
public Book getById(Integer id){
return bookDao.getById(id);
}; // 查
public List<Book> selectAll(){
return bookDao.selectAll();
}; // 查全部
}
2.5 controller层 ★
- 先配置注解
@Controller
; - 然后直接在类上添加
@RequestMapping(“/books”)
设置公共访问路径; - 要调业务层接口,就要service类的成员变量和bean; 自动装配
@Autowird
; - @RequestMapping简写为
@GetMapping
、@DeleteMapping
等; - 设置传入参数,请求体获取的在参数前加
@RequestBody
,url参数@RequestParam
,@PathVariable
为接收路径中的请求参数;
@Controller
@RequestMapping("/books")
public class BookController {
@Autowired
private BookService bookService; // 需要业务层的bean
@PostMapping //参数从请求体获取, POST对应insert
public boolean save(@RequestBody Book book){
return bookService.save(book);
}; // 增
@DeleteMapping("/{id}") // 参数从路径获取
public boolean delete(@PathVariable Integer id){
return bookService.delete(id);
}; // 删
@PutMapping // 参数从请求体获取,PUT对应 update
public boolean update(@RequestBody Book book){
return bookService.update(book);
}; // 改
@GetMapping("/{id}") // GET对应select
public Book getById(@PathVariable Integer id){
return bookService.getById(id);
}; // 查
@GetMapping
public List<Book> selectAll(){
return bookService.selectAll();
}; // 查全部
}
补充:PUT和POST区别?
PUT请求:如果两个请求相同,后一个请求会把第一个请求覆盖掉。(所以PUT用来改资源,对应update)
POST请求:后一个请求不会把第一个请求覆盖掉。(所以Post用来增加源,对应insert)
到这里,后台模块暂时完成;
业务层完称后,使用用Junit做测试;-------------测试1
表现层完成后,使用postman做表现层测试--------------测试2
遇到的问题:
- mapper的xml配置文件目录是com.abc.dao 是三层文件夹,而不是文件名为“com.abc.dao”;
- 数据库时区错误,在url后面加
?serverTimezone=UTC
; - @PropertySource(
classpath:
jdbc.properties),不加classpath: 就会找不到properties文件;
三.测试
3.1 业务层测试
运行test,打印出结果:
3.2表现层测试
-
先运行 Run Maven- Tomcat7:run 试试:
成功开启Tomcat服务器;
-
测试表现层的save()方法,对应使用POST的请求方式,根据REST法则,路径为公共路径
/books
REST法则:
-
使用postman进行前端测试:
在json中传入要insert的数据;
结果:在数据库中成功添加数据;
遇到的问题:
- controller注释的是
@RestController
而不是 @Controller,因为json的反序列化需要@RequestBody
,和@Controller合并; - 在SpringMvcConfig中开启
@EnableWebMvc
- sql写错,在mapper映射文件中改正;