0%

ssm-study

整合SpringSpringMVCMybatis 框架

SpringMVC :用于 web 层,相当于 controller(等价于传统的 servlet struts action),用来处理用户请求。举个例子,用户在浏览器地址栏中输入 http://网站域名/login,那么 SpringMVC 就会拦截到这个请求,并且调用 controller 层中相应的方法,(中间可能包含验证用户名和密码的业务逻辑,以及查询数据库操作,但这些都不是 SpringMVC 的职责),最终把结果返回给用户,并且返回相应的页面(也可以指返回 json/xml 等格式数据)。 SpringMVC 就是做前面和后面过程的工作,与用户打交道。

Spring:非常强大,无法用一个词或者一句话来概括它。但与平时开发接触最多的是 IOC 容器,它可以装载 bean,有了这个机制,我们就不用每次使用这个类的时候为它初始化,很少看到关键字 new,另外,SpringAOP,事务管理等都是我们经常用到的。

Mybatis :能自由控制 sql,这会让有数据库经验的人编写的代码能提升数据库访问的效率;它可以使用 xml 的方式组织管理我们的 sql,因为一般程序出错很多情况下是 sql 出错,别人接手代码后能快速找到出错地方,甚至可以优化原来写的 sql

项目结构

使用 IDEA 创建一个 Maven 工程,添加 web 框架支持,我们的工程目录结构如下所示:

project
├─src
│ ├─main
│ │ ├─java
│ │ └─resources
│ └─test
│ └─java
└─web
└─WEB-INF

文件名 作用
src 根目录,下面有 maintest
java 存放 java 代码,这个文件夹要使用 Build Path -> Use as Source Folder
resources 存放资源文件,譬如各种的 SpringMybatislog 配置文件。
web 用来存放我们前端的静态资源,如 jsp js css
WEB-INF 外部浏览器无法访问,只有内部才能访问,可以把 jsp放在这里,另外就是 web.xml 了。

通常新建的几个包有 dao, dto, entity, service, controller

包名 名称 作用
dao/mapper 数据访问层(接口) 与数据打交道,可以是数据库操作,也可以是文件读写操作,甚至是 redis 缓存操作,总之与数据操作有关的都放在这里,也有人叫做 dal 或者数据持久层。
entity/pojo 实体类 一般与数据库的表相对应,封装 dao 层取出来的数据为一个对象,一般只在dao层与service层之间传输。
dto/vo 数据传输层 用于service层与web层之间传输,在实际开发中,很多时间一个entity并不能满足我们的业务需求,可能呈现给用户的信息十分之多,这时候就有了dto,也相当于vo
service 业务逻辑(接口) 写我们的业务逻辑
serviceImpl 业务逻辑(实现) 实现我们业务接口,一般事务控制是写在这里
controller 控制器 springmvc就是在这里发挥作用的,相当于struts中的action。

使用maven导入相应的jar包:在pom.xml中加入相应的依赖

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
<?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.chenpeng</groupId>
<artifactId>library</artifactId>
<version>1.0-SNAPSHOT</version>
<dependencies>
<!--单元测试-->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.13</version>
<scope>test</scope>
</dependency>

<!--spring框架支持-->
<!--spring-context中包含了spring-aop, spring-beans, spring-core, spring-expression-->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.2.7.RELEASE</version>
</dependency>
<!-- spring-jdbc驱动 -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>5.2.7.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>5.2.7.RELEASE</version>
</dependency>

<!-- mybatis支持 -->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.5.5</version>
</dependency>
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis-spring</artifactId>
<version>2.0.5</version>
</dependency>

<!-- mysql支持 -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.21</version>
</dependency>

<!-- 数据源 dataSource-->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.2.6</version>
</dependency>
<!-- 日志 -->
<!-- 实现slf4j接口并整合 -->
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
<version>1.3.0-alpha10</version>
</dependency>

<!-- 添加jsp依赖 -->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>4.0.1</version>
</dependency>
<dependency>
<groupId>jstl</groupId>
<artifactId>jstl</artifactId>
<version>1.2</version>
</dependency>
</dependencies>

<!-- 设置 mapper 过滤 -->
<build>
<resources>
<resource>
<directory>src/main/java</directory>
<includes>
<include>**/*.properties</include>
<include>**/*.xml</include>
</includes>
<filtering>false</filtering>
</resource>
<resource>
<directory>src/main/resources</directory>
<includes>
<include>**/*.properties</include>
<include>**/*.xml</include>
</includes>
<filtering>false</filtering>
</resource>
</resources>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>6</source>
<target>6</target>
</configuration>
</plugin>
</plugins>
</build>
</project>

spring 配置

因为spring的配置太多,这里分三层,分别是 mapper,service,controller

mapper 层

在 resources 文件夹下新建 spring-mapper.xml 文件,

  1. 读入数据库连接相关参数
  2. 配置数据源 dataSource
  3. 配置 SqlSessionFactory 对象
  4. 扫描 mapper 层接口,动态实现 mapper 接口,也就是说不需要手动实现 mapper 接口,sql和参数都写在 xml 文件上

spring-mapper.xml

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
<?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"
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">
<!-- 配置整合mybatis过程 -->
<!-- 1.配置数据库相关参数properties的属性:${url} -->
<context:property-placeholder location="classpath:jdbc.properties" />

<!-- 2.数据库连接池 -->
<bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource">
<!-- 配置连接池属性 -->
<property name="driverClassName" value="${jdbc.driver}" />
<property name="url" value="${jdbc.url}" />
<property name="username" value="${jdbc.username}" />
<property name="password" value="${jdbc.password}" />
</bean>

<!-- 3.配置SqlSessionFactory对象 -->
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<!-- 注入数据库连接池 -->
<property name="dataSource" ref="dataSource" />
<!-- 配置MyBatis全局配置文件:mybatis-config.xml -->
<property name="configLocation" value="classpath:mybatis-config.xml" />
<!-- 扫描pojo包 使用别名 -->
<property name="typeAliasesPackage" value="com.chenpeng.pojo" />
<!-- 扫描sql配置文件:mapper需要的xml文件 -->
<property name="mapperLocations" value="classpath:*.xml" />
</bean>

<!-- 4.配置扫描Dao接口包,动态实现Dao接口,注入到spring容器中 -->
<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
<!-- 注入sqlSessionFactory -->
<property name="sqlSessionFactoryBeanName" value="sqlSessionFactory" />
<!-- 给出需要扫描Dao接口包 -->
<property name="basePackage" value="com.chenpeng.dao" />
</bean>
</beans>

resources 文件夹下新建 jdbc.properties 文件,存放数据库连接属性。

jdbc.properties

1
2
3
4
jdbc.driver=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3307/ssm?useUnicode=true&characterEncoding=utf8
jdbc.username=root
jdbc.password=

mybatis 全局配置文件:resources文件夹下新建mybatis-config.xml文件,此为mybatis核心文件

  1. 使用自增主键
  2. 使用列别名
  3. 开启驼峰明明转换 create_time -> createTime
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration
PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
<!-- 配置全局属性 -->
<settings>
<!-- 使用jdbc的getGeneratedKeys获取数据库自增主键值 -->
<setting name="useGeneratedKeys" value="true" />

<!-- 使用列别名替换列名 默认:true -->
<setting name="useColumnLabel" value="true" />

<!-- 开启驼峰命名转换:Table{create_time} -> Entity{createTime} -->
<setting name="mapUnderscoreToCamelCase" value="true" />
</settings>
</configuration>

service层

创建spring-service.xml文件

1
2
3
4
5
6
7
<?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:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd">
</beans>
  1. 扫描service包所有注解@Service
  2. 配置事务管理器,把事务管理由spring来完成
  3. 配置基于注解的声明式事务,可以直接在方法上使用注解@Transaction
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
<?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"
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/tx
http://www.springframework.org/schema/tx/spring-tx.xsd">

<!-- 扫描service包下所有使用注解的类型 -->
<context:component-scan base-package="com.chenpeng.service" />

<!-- 配置事务管理器 -->
<bean id="transactionManager"
class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<!-- 注入数据库连接池 -->
<property name="dataSource" ref="dataSource" />
</bean>

<!-- 配置基于注解的声明式事务 -->
<tx:annotation-driven transaction-manager="transactionManager" />
</beans>

controller层

创建 spring-controller.xml 文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd">

<!--添加处理器映射器-->
<bean class="org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping"/>
<!--添加处理器适配器-->
<bean class="org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter"/>

<!-- 添加视图解析器 -->
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="viewClass" value="org.springframework.web.servlet.view.JstlView" />
<property name="prefix" value="/WEB-INF/jsp/" />
<property name="suffix" value=".jsp" />
</bean>

<!-- 注册 controller 相关bean -->
</beans>
  1. 开启springmvc注解模式,可以使用注解@RequestMapping @PathVariable @ ResponseBody等
  2. 对静态资源处理,如js,css,jpg等
  3. 配置jsp显示viewResolver,例如在controller中某个方法返回一个string类型“login”,实际上会返回“/WEB-INF/login.jsp”
  4. 扫描controller层 @Controller
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
<?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
http://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd">
<!-- 配置SpringMVC -->
<!-- 1.开启SpringMVC注解模式 -->
<!-- 简化配置:
(1)自动注册DefaultAnootationHandlerMapping,AnotationMethodHandlerAdapter
(2)提供一些列:数据绑定,数字和日期的format @NumberFormat, @DateTimeFormat, xml,json默认读写支持
-->
<mvc:annotation-driven />

<!-- 2.静态资源默认servlet配置
(1)加入对静态资源的处理:js,gif,png
(2)允许使用"/"做整体映射
-->
<mvc:default-servlet-handler/>

<!-- 3.配置jsp 显示ViewResolver -->
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="viewClass" value="org.springframework.web.servlet.view.JstlView" />
<property name="prefix" value="/WEB-INF/jsp/" />
<property name="suffix" value=".jsp" />
</bean>

<!-- 4.扫描web相关的bean -->
<context:component-scan base-package="com.chenpeng.controller" />
</beans>

数据准备

首先创建数据库 library,再创建数据表 book,并且为 book 表初始化一些数据。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
-- 创建图书表
CREATE TABLE `book` (
`book_id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '图书ID',
`name` varchar(100) NOT NULL COMMENT '图书名称',
`number` int(11) NOT NULL COMMENT '馆藏数量',
PRIMARY KEY (`book_id`)
) ENGINE=InnoDB AUTO_INCREMENT=1000 DEFAULT CHARSET=utf8 COMMENT='图书表';

-- 初始化图书数据
INSERT INTO `book` (`book_id`, `name`, `number`)
VALUES
(1000, 'Java程序设计', 10),
(1001, '数据结构', 10),
(1002, '设计模式', 10),
(1003, '编译原理', 10);

编写实体类

在 java 目录下创建文件夹 com.chenpeng.pojo,这个文件夹下存放的是我们的实体类,一般与数据库中的表对应。

Book.java

1
2
3
4
5
6
public class Book {
private int id;
private String name;
private int num;
// 省略构造方法,getter 和 setter 方法,以及 toString 方法
}

Mapper 层

创建 mapper 目录,这个目录下存放的是我们的 mapper 接口和配置文件 xxMapper.xml

BookMapper.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
public interface BookMapper {
/**
* 根据图书id查询图书信息
* @param bookId 图书id
* @return 根据id查询的图书信息
*/
Book selectById(long bookId);

/**
* 查询所有图书
*
* @param start 查询起始位置
* @param limit 查询条数
* @return 图书列表
*/
List<Book> queryAll(@Param("start") int start, @Param("limit") int limit);

/**
* 减少馆藏数量
*
* @param bookId 图书编号
* @return 如果影响行数等于>1,表示更新的记录行数
*/
int reduceNumber(long bookId);
}

BookMapper.xml

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.chenpeng.mapper.BookMapper">
<!-- <resultMap id="bookResultMap" type="com.chenpeng.pojo.book">-->
<!-- <id property="bookId" column="book_id"/>-->
<!-- </resultMap>-->
<select id="selectById" resultType="com.chenpeng.pojo.Book" parameterType="long">
SELECT book_id,
name,
number
FROM book
WHERE book_id = #{bookId}
</select>

<select id="queryAll" resultType="com.chenpeng.pojo.Book">
SELECT book_id,
name,
number
FROM book
ORDER BY book_id
LIMIT #{start}, #{limit}
</select>
</mapper>

Service 层

创建 service 目录,这个文件夹下存放的是我们的业务逻辑接口及其 bean 实现

BookService.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
public interface BookService {

/**
* 查询一本图书
*
* @param bookId 图书编号
* @return 图书信息
*/
Book getById(long bookId);

/**
* 查询所有图书
*
* @return 图书信息列表
*/
List<Book> getList();
}

BookServiceImpl.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
public class BookServiceImpl implements BookService {

private final Logger logger = LoggerFactory.getLogger(this.getClass());
private BookMapper bookMapper;
private AppointmentMapper appointmentMapper;

@Override
public Book getById(long bookId) {
return bookMapper.selectById(bookId);
}

@Override
public List<Book> getList() {
return bookMapper.queryAll(0, 1000);
}
// 省略构造方法,getter 和 setter 方法,以及 toString 方法
}

将我们实现完成的 bean 注册到 spring-service.xml 文件中

1
2
3
<bean id="bookService" class="com.chenpeng.service.serviceImpl.BookServiceImpl">
<property name="bookMapper" ref="bookMapper"/>
</bean>

controller 层

创建 controller 文件夹,该目录下存放的是我们用来接收前端请求和与后台交互的 controller 类

BookController.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
public class BookController implements Controller {

private final Logger logger = LoggerFactory.getLogger(this.getClass());
private BookService bookService;

@Override
public ModelAndView handleRequest(HttpServletRequest request, HttpServletResponse response) throws Exception {
List<Book> list = bookService.getList();
ModelAndView modelAndView = new ModelAndView();
modelAndView.addObject("list", list);
modelAndView.setViewName("/allBook");
return modelAndView;
}

public BookService getBookService() {
return bookService;
}
// 省略 setter 方法
}
将 BookController.java 作为 bean 注册到 spring-controller 中
1
2
3
<bean id="/allBook" class="com.chenpeng.controller.BookController">
<property name="bookService" ref="bookService"/>
</bean>

前端显示 allBook.jsp

1
2
3
4
5
6
7
8
9
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<body>
${list}
</body>
</html>

测试

配置 tomcat 服务器,并启动项目

在浏览器地址栏输入:http://localhost:8080/library/allBook

image-20210917225449559

使用注解开发

参考资料

手把手教你整合最优雅SSM框架:SpringMVC + Spring + MyBatis_小疯的代码健身房-CSDN博客

史上最详细的IDEA优雅整合Maven+SSM框架(详细思路+附带源码)_宜春-CSDN博客_ssm框架idea整合代码