本文系统性梳理了 SSM 框架整合的关键概念与实战配置,围绕 IoC 容器数量、组件归属、配置类划分与初始化方式等核心问题展开深入分析,并通过完整的案例演示,介绍了从依赖整合到前后端联调的全过程。文章后半部分以“任务列表系统”为示例,讲解前端环境搭建、后端功能实现及接口对接的详细流程,帮助读者在理解 SSM 原理的基础上,掌握实际开发中的整合技巧与调试方法,适合有一定基础的读者查漏补缺或快速上手 SSM 框架整合开发。
一、SSM 整合理解
1.1 什么是 SSM 整合?
微观:将学习的 Spring SpringMVC Mybatis 框架应用到项目中!
- SpringMVC 框架负责控制层
- Spring 框架负责整体和业务层的声明式事务管理
- MyBatis 框架负责数据库访问层
宏观:Spring 接管一切(将框架核心组件交给 Spring 进行 IoC 管理),代码更加简洁。
- SpringMVC 管理表述层、SpringMVC 相关组件
- Spring 管理业务层、持久层、以及数据库相关(DataSource,MyBatis)的组件
- 使用 IoC 的方式管理一切所需组件
实施:通过编写配置文件,实现 SpringIoC 容器接管一切组件。
1.2 SSM 整合核心问题明确
1.2.1 第一问:SSM 整合需要几个 IoC 容器?
两个容器
本质上说,整合就是将三层架构和框架核心 API 组件交给 SpringIoC 容器管理!
一个容器可能就够了,但是我们常见的操作是创建两个 IoC 容器(web 容器和 root 容器),组件分类管理!
这种做法有以下好处和目的:
- 分离关注点:通过初始化两个容器,可以将各个层次的关注点进行分离。这种分离使得各个层次的组件能够更好地聚焦于各自的责任和功能。
- 解耦合:各个层次组件分离装配不同的 IoC 容器,这样可以进行解耦。这种解耦合使得各个模块可以独立操作和测试,提高了代码的可维护性和可测试性。
- 灵活配置:通过使用两个容器,可以为每个容器提供各自的配置,以满足不同层次和组件的特定需求。每个配置文件也更加清晰和灵活。
总的来说,初始化两个容器在 SSM 整合中可以实现关注点分离、解耦合、灵活配置等好处。它们各自负责不同的层次和功能,并通过合适的集成方式协同工作,提供一个高效、可维护和可扩展的应用程序架构!
1.2.2 第二问:每个 IoC 容器对应哪些类型组件?
总结:
容器名 | 盛放组件 |
---|---|
web 容器 | web 相关组件(controller,springmvc 核心组件) |
root 容器 | 业务和持久层相关组件(service,aop,tx,dataSource,mybatis,mapper 等) |
1.2.3 第三问:IoC 容器之间关系和调用方向?
情况 1:两个无关联 IoC 容器之间的组件无法注入!
情况 2:子 IoC 容器可以单向的注入父 IoC 容器的组件!
结论:web 容器是 root 容器的子容器。
- 父容器:root 容器,盛放 service、mapper、mybatis 等相关组件
- 子容器:web 容器,盛放 controller、web 相关组件
源码体现:
FrameworkServlet 655 行!
1 | protected WebApplicationContext createWebApplicationContext( { ApplicationContext parent) |
调用流程图解:
1.2.4 第四问:具体多少配置类以及对应容器关系?
配置类的数量不是固定的,但是至少要两个,为了方便编写,我们可以三层架构每层对应一个配置类,分别指定两个容器加载即可!
建议配置文件:
配置名 | 对应内容 | 对应容器 |
---|---|---|
WebJavaConfig | controller,springmvc 相关 | web 容器 |
ServiceJavaConfig | service,aop,tx 相关 | root 容器 |
MapperJavaConfig | mapper,datasource,mybatis 相关 | root 容器 |
1.2.5 第五问:IoC 初始化方式和配置位置?
在 web 项目下,我们可以选择 web.xml 和配置类方式进行 ioc 配置,推荐配置类。
对于使用基于 web 的 Spring 配置的应用程序,建议这样做,如以下示例所示:
1 | public class MyWebAppInitializer extends AbstractAnnotationConfigDispatcherServletInitializer { |
二、SSM 整合配置实战
2.1 依赖整合和添加
数据库准备
依然沿用 mybatis 数据库测试脚本!
1
2
3
4
5
6
7
8
9
10
11
12
13
14CREATE DATABASE `mybatis-example`;
USE `mybatis-example`;
CREATE TABLE `t_emp`(
emp_id INT AUTO_INCREMENT,
emp_name CHAR(100),
emp_salary DOUBLE(10,5),
PRIMARY KEY(emp_id)
);
INSERT INTO `t_emp`(emp_name,emp_salary) VALUES("tom",200.33);
INSERT INTO `t_emp`(emp_name,emp_salary) VALUES("jerry",666.66);
INSERT INTO `t_emp`(emp_name,emp_salary) VALUES("andy",777.77);准备项目
转成 web 项目
依赖导入
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
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
<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.atguigu</groupId>
<artifactId>part04-ssm-integration</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>war</packaging>
<properties>
<spring.version>6.0.6</spring.version>
<jakarta.annotation-api.version>2.1.1</jakarta.annotation-api.version>
<jakarta.jakartaee-web-api.version>9.1.0</jakarta.jakartaee-web-api.version>
<jackson-databind.version>2.15.0</jackson-databind.version>
<hibernate-validator.version>8.0.0.Final</hibernate-validator.version>
<mybatis.version>3.5.11</mybatis.version>
<mysql.version>8.0.25</mysql.version>
<pagehelper.version>5.1.11</pagehelper.version>
<druid.version>1.2.8</druid.version>
<mybatis-spring.version>3.0.2</mybatis-spring.version>
<jakarta.servlet.jsp.jstl-api.version>3.0.0</jakarta.servlet.jsp.jstl-api.version>
<logback.version>1.2.3</logback.version>
<lombok.version>1.18.26</lombok.version>
<maven.compiler.source>17</maven.compiler.source>
<maven.compiler.target>17</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<!--
需要依赖清单分析:
spring
ioc/di
spring-context / 6.0.6
jakarta.annotation-api / 2.1.1 jsr250
aop
spring-aspects / 6.0.6
tx
spring-tx / 6.0.6
spring-jdbc / 6.0.6
springmvc
spring-webmvc 6.0.6
jakarta.jakartaee-web-api 9.1.0
jackson-databind 2.15.0
hibernate-validator / hibernate-validator-annotation-processor 8.0.0.Final
mybatis
mybatis / 3.5.11
mysql / 8.0.25
pagehelper / 5.1.11
整合需要
加载spring容器 spring-web / 6.0.6
整合mybatis mybatis-spring x x
数据库连接池 druid / x
lombok lombok / 1.18.26
logback logback/ 1.2.3
-->
<dependencies>
<!--spring pom.xml依赖-->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>jakarta.annotation</groupId>
<artifactId>jakarta.annotation-api</artifactId>
<version>${jakarta.annotation-api.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aop</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aspects</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-tx</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>${spring.version}</version>
</dependency>
<!--
springmvc
spring-webmvc 6.0.6
jakarta.jakartaee-web-api 9.1.0
jackson-databind 2.15.0
hibernate-validator / hibernate-validator-annotation-processor 8.0.0.Final
-->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>jakarta.platform</groupId>
<artifactId>jakarta.jakartaee-web-api</artifactId>
<version>${jakarta.jakartaee-web-api.version}</version>
<scope>provided</scope>
</dependency>
<!-- jsp需要依赖! jstl-->
<dependency>
<groupId>jakarta.servlet.jsp.jstl</groupId>
<artifactId>jakarta.servlet.jsp.jstl-api</artifactId>
<version>${jakarta.servlet.jsp.jstl-api.version}</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>${jackson-databind.version}</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.hibernate.validator/hibernate-validator -->
<dependency>
<groupId>org.hibernate.validator</groupId>
<artifactId>hibernate-validator</artifactId>
<version>${hibernate-validator.version}</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.hibernate.validator/hibernate-validator-annotation-processor -->
<dependency>
<groupId>org.hibernate.validator</groupId>
<artifactId>hibernate-validator-annotation-processor</artifactId>
<version>${hibernate-validator.version}</version>
</dependency>
<!--
mybatis
mybatis / 3.5.11
mysql / 8.0.25
pagehelper / 5.1.11
-->
<!-- mybatis依赖 -->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>${mybatis.version}</version>
</dependency>
<!-- MySQL驱动 mybatis底层依赖jdbc驱动实现,本次不需要导入连接池,mybatis自带! -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>${mysql.version}</version>
</dependency>
<dependency>
<groupId>com.github.pagehelper</groupId>
<artifactId>pagehelper</artifactId>
<version>${pagehelper.version}</version>
</dependency>
<!-- 整合第三方特殊依赖 -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-web</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis-spring</artifactId>
<version>${mybatis-spring.version}</version>
</dependency>
<!-- 日志 , 会自动传递slf4j门面-->
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
<version>${logback.version}</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>${lombok.version}</version>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>${druid.version}</version>
</dependency>
</dependencies>
</project>实体类添加
com.atguigu.pojo
1
2
3
4
5
6
7
public class Employee {
private Integer empId;
private String empName;
private Double empSalary;
}logback 配置
位置:resources/logback.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
<configuration debug="true">
<!-- 指定日志输出的位置,ConsoleAppender表示输出到控制台 -->
<appender name="STDOUT"
class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<!-- 日志输出的格式 -->
<!-- 按照顺序分别是:时间、日志级别、线程名称、打印日志的类、日志主体内容、换行 -->
<pattern>[%d{HH:mm:ss.SSS}] [%-5level] [%thread] [%logger] [%msg]%n</pattern>
<charset>UTF-8</charset>
</encoder>
</appender>
<!-- 设置全局日志级别。日志级别按顺序分别是:TRACE、DEBUG、INFO、WARN、ERROR -->
<!-- 指定任何一个日志级别都只打印当前级别和后面级别的日志。 -->
<root level="DEBUG">
<!-- 指定打印日志的appender,这里通过“STDOUT”引用了前面配置的appender -->
<appender-ref ref="STDOUT" />
</root>
<!-- 根据特殊需求指定局部日志级别,可也是包名或全类名。 -->
<logger name="com.atguigu.mybatis" level="DEBUG" />
</configuration>
2.2 控制层配置编写(SpringMVC 整合)
主要配置 controller,springmvc 相关组件配置
位置:WebJavaConfig.java(命名随意)
1 | /** |
2.3 业务层配置编写(AOP / TX 整合)
主要配置 service,注解 aop 和声明事务相关配置
位置:ServiceJavaConfig.java(命名随意)
1 | /** |
2.4 持久层配置编写(MyBatis 整合)
主要配置 mapper 代理对象,连接池和 mybatis 核心组件配置
mybatis 整合思路
mybatis 核心 api 使用回顾:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16//1.读取外部配置文件
InputStream ips = Resources.getResourceAsStream("mybatis-config.xml");
//2.创建sqlSessionFactory
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(ips);
//3.创建sqlSession
SqlSession sqlSession = sqlSessionFactory.openSession();
//4.获取mapper代理对象
EmpMapper empMapper = sqlSession.getMapper(EmpMapper.class);
//5.数据库方法调用
int rows = empMapper.deleteEmpById(1);
System.out.println("rows = " + rows);
//6.提交和回滚
sqlSession.commit();
sqlSession.close();mybatis 核心 api 介绍回顾:
SqlSessionFactoryBuilder
这个类可以被实例化、使用和丢弃,一旦创建了 SqlSessionFactory,就不再需要它了。 因此 SqlSessionFactoryBuilder 实例的最佳作用域是方法作用域(也就是局部方法变量)。 无需 ioc 容器管理!
SqlSessionFactory
一旦被创建就应该在应用的运行期间一直存在,没有任何理由丢弃它或重新创建另一个实例。 使用 SqlSessionFactory 的最佳实践是在应用运行期间不要重复创建多次,因此 SqlSessionFactory 的最佳作用域是应用作用域。 需要 ioc 容器管理!
SqlSession
每个线程都应该有它自己的 SqlSession 实例。SqlSession 的实例不是线程安全的,因此是不能被共享的,所以它的最佳的作用域是请求或方法作用域。 无需 ioc 容器管理!
Mapper 映射器实例
映射器是一些绑定映射语句的接口。映射器接口的实例是从 SqlSession 中获得的。虽然从技术层面上来讲,任何映射器实例的最大作用域与请求它们的 SqlSession 相同。但方法作用域才是映射器实例的最合适的作用域。
从作用域的角度来说,映射器实例不应该交给 ioc 容器管理!
但是从使用的角度来说,业务类(service)需要注入 mapper 接口,所以 mapper 应该交给 ioc 容器管理!
总结
- 将 SqlSessionFactory 实例存储到 IoC 容器
- 将 Mapper 实例存储到 IoC 容器
例如,自己实现 sqlSessionFactory 加入 ioc 容器:
1
2
3
4
5
6
7
8
9
10
public SqlSessionFactory sqlSessionFactory(){
//1.读取外部配置文件
InputStream ips = Resources.getResourceAsStream("mybatis-config.xml");
//2.创建sqlSessionFactory
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(ips);
return sqlSessionFactory;
}过程比较繁琐,为了提高整合效率,mybatis 提供了提供封装 SqlSessionFactory 和 Mapper 实例化的逻辑的 FactoryBean 组件,我们只需要声明和指定少量的配置即可!
SqlSessionFactoryBean 源码展示(mybatis 提供):
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16package org.mybatis.spring;
public class SqlSessionFactoryBean
implements FactoryBean<SqlSessionFactory>, InitializingBean, ApplicationListener<ContextRefreshedEvent> {
//封装了实例化流程
public SqlSessionFactory getObject() throws Exception {
if (this.sqlSessionFactory == null) {
//实例化对象逻辑
afterPropertiesSet();
}
//返回对象逻辑
return this.sqlSessionFactory;
}
}mybatis 整合思路总结:
- 需要将 SqlSessionFactory 和 Mapper 实例加入到 IoC 容器
- 使用 mybatis 整合包提供的 FactoryBean 快速整合
准备外部配置文件
数据库连接信息 位置:resources/jdbc.properties
1
2
3
4jdbc.user=root
jdbc.password=root
jdbc.url=jdbc:mysql:///mybatis-example
jdbc.driver=com.mysql.cj.jdbc.Driver整合方式 2(完全配置类 去掉 mybatis-config.xml)
介绍
不在保留 mybatis 的外部配置文件(xml), 所有配置信息(settings、插件、别名等)全部在声明 SqlSessionFactoryBean 的代码中指定!数据库信息依然使用 DruidDataSource 实例替代!
优势:全部配置类,避免了 XML 文件解析效率低问题!
mapper 配置类
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/**
* projectName: com.atguigu.config
*
* description: 持久层配置和Druid和Mybatis配置 使用一个配置文件
*/
public class MapperJavaConfigNew {
/**
* 配置SqlSessionFactoryBean,指定连接池对象和外部配置文件即可
* @param dataSource 需要注入连接池对象
* @return 工厂Bean
*/
public SqlSessionFactoryBean sqlSessionFactoryBean(DataSource dataSource){
//实例化SqlSessionFactory工厂
SqlSessionFactoryBean sqlSessionFactoryBean = new SqlSessionFactoryBean();
//设置连接池
sqlSessionFactoryBean.setDataSource(dataSource);
//settings [包裹到一个configuration对象,切记别倒错包]
org.apache.ibatis.session.Configuration configuration = new org.apache.ibatis.session.Configuration();
configuration.setMapUnderscoreToCamelCase(true);
configuration.setLogImpl(Slf4jImpl.class);
configuration.setAutoMappingBehavior(AutoMappingBehavior.FULL);
sqlSessionFactoryBean.setConfiguration(configuration);
//typeAliases
sqlSessionFactoryBean.setTypeAliasesPackage("com.atguigu.pojo");
//分页插件配置
PageInterceptor pageInterceptor = new PageInterceptor();
Properties properties = new Properties();
properties.setProperty("helperDialect","mysql");
pageInterceptor.setProperties(properties);
sqlSessionFactoryBean.addPlugins(pageInterceptor);
return sqlSessionFactoryBean;
}
/**
* 配置Mapper实例扫描工厂,配置 <mapper <package 对应接口和mapperxml文件所在的包
* @return
*/
public MapperScannerConfigurer mapperScannerConfigurer(){
MapperScannerConfigurer mapperScannerConfigurer = new MapperScannerConfigurer();
//设置mapper接口和xml文件所在的共同包
mapperScannerConfigurer.setBasePackage("com.atguigu.mapper");
return mapperScannerConfigurer;
}
}
2.5 容器初始化配置类
1 | public class MyWebAppInitializer extends AbstractAnnotationConfigDispatcherServletInitializer { |
2.6 整合测试
需求
查询所有员工信息,返回对应 json 数据!
controller
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
public class EmployeeController {
private EmployeeService employeeService;
public List<Employee> retList(){
List<Employee> employees = employeeService.findAll();
log.info("员工数据:{}",employees);
return employees;
}
}service
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
public class EmployeeServiceImpl implements EmployeeService {
private EmployeeMapper employeeMapper;
/**
* 查询所有员工信息
*/
public List<Employee> findAll() {
List<Employee> employeeList = employeeMapper.queryAll();
return employeeList;
}
}mapper
mapper 接口 包:com.atguigu.mapper
1
2
3public interface EmployeeMapper {
List<Employee> queryAll();
}mapper XML 文件位置: resources/mappers
1
2
3
4
5
6
7
8
9
10
11
12
13
<!-- namespace等于mapper接口类的全限定名,这样实现对应 -->
<mapper namespace="com.atguigu.mapper.EmployeeMapper">
<select id="queryAll" resultType="employee">
<!-- #{empId}代表动态传入的参数,并且进行赋值!后面详细讲解 -->
select emp_id empId,emp_name empName, emp_salary empSalary from t_emp
</select>
</mapper>
三、《任务列表案例》前端程序搭建和运行
3.1 整合案例介绍和接口分析
3.1.1 案例功能预览
3.1.2 接口分析
学习计划分页查询
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/*
需求说明
查询全部数据页数据
请求uri
schedule/{pageSize}/{currentPage}
请求方式
get
响应的json
{
"code":200,
"flag":true,
"data":{
//本页数据
data:
[
{id:1,title:'学习java',completed:true},
{id:2,title:'学习html',completed:true},
{id:3,title:'学习css',completed:true},
{id:4,title:'学习js',completed:true},
{id:5,title:'学习vue',completed:true}
],
//分页参数
pageSize:5, // 每页数据条数 页大小
total:0 , // 总记录数
currentPage:1 // 当前页码
}
}
*/学习计划删除
1
2
3
4
5
6
7
8
9
10
11
12
13
14/*
需求说明
根据id删除日程
请求uri
schedule/{id}
请求方式
delete
响应的json
{
"code":200,
"flag":true,
"data":null
}
*/学习计划保存
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19/*
需求说明
增加日程
请求uri
schedule
请求方式
post
请求体中的JSON
{
title: '',
completed: false
}
响应的json
{
"code":200,
"flag":true,
"data":null
}
*/学习计划修改
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20/*
需求说明
根据id修改数据
请求uri
schedule
请求方式
put
请求体中的JSON
{
id: 1,
title: '',
completed: false
}
响应的json
{
"code":200,
"flag":true,
"data":null
}
*/
3.2 前端工程导入
3.2.1 前端环境搭建
Node.js 是前端程序运行的服务器,类似 Java 程序运行的服务器 Tomcat Npm 是前端依赖包管理工具,类似 maven 依赖管理工具软件
node 安装
课程 node 版本:16.16.0
https://nodejs.org/download/release/v16.16.0/
node 安装和测试:
打开官网 https://nodejs.org/en/ 下载对应操作系统的 LTS 版本。(16.16.0)
[node-v16.16.0-x64.msi](file/node-v16.16.0-x64_NU23iPcrzB.msi ” node-v16.16.0-x64.msi”)
双击安装包进行安装,安装过程中遵循默认选项即可。安装完成后,可以在命令行终端输入
node -v
和npm -v
查看 Node.js 和 npm 的版本号。
npm 使用 (maven)
NPM 全称 Node Package Manager,是 Node.js 包管理工具,相当于后端的 Maven。
配置阿里镜像
1
npm config set registry https://registry.npmjs.org/
更新 npm 版本 node16.16.0 对应的 npm 版本过低!需要升级!
1
npm install -g npm@9.6.6
npm 依赖下载命令
1
npm install 依赖名 / npm install 依赖名@版本
安装 vscode
[VSCodeUserSetup-x64-1.74.0.exe](file/VSCodeUserSetup-x64-1.74.0_byHx-Ntjau.exe ” VSCodeUserSetup-x64-1.74.0.exe”)
3.2.2 导入前端程序
3.3 启动测试
1 | npm install //安装依赖 |
四、《任务列表案例》后端程序实现和测试
4.1 准备工作
准备数据库脚本
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
30CREATE TABLE schedule (
id INT NOT NULL AUTO_INCREMENT,
title VARCHAR(255) NOT NULL,
completed BOOLEAN NOT NULL,
PRIMARY KEY (id)
);
INSERT INTO schedule (title, completed)
VALUES
('学习java', true),
('学习Python', false),
('学习C++', true),
('学习JavaScript', false),
('学习HTML5', true),
('学习CSS3', false),
('学习Vue.js', true),
('学习React', false),
('学习Angular', true),
('学习Node.js', false),
('学习Express', true),
('学习Koa', false),
('学习MongoDB', true),
('学习MySQL', false),
('学习Redis', true),
('学习Git', false),
('学习Docker', true),
('学习Kubernetes', false),
('学习AWS', true),
('学习Azure', false);准备 pojo
包:com.atguigu.pojo
1
2
3
4
5
6
7
8
public class Schedule {
private Integer id;
private String title;
private Boolean completed;
}准备
包:com.atguigu.utils
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
public class R {
private int code = 200; //200成功状态码
private boolean flag = true; //返回状态
private Object data; //返回具体数据
public static R ok(Object data){
R r = new R();
r.data = data;
return r;
}
public static R fail(Object data){
R r = new R();
r.code = 500; //错误码
r.flag = false; //错误状态
r.data = data;
return r;
}
}准备 PageBean
包:com.atguigu.utils
1
2
3
4
5
6
7
8
9
public class PageBean<T> {
private int currentPage; // 当前页码
private int pageSize; // 每页显示的数据量
private long total; // 总数据条数
private List<T> data; // 当前页的数据集合
}
4.2 功能实现
分页查询
controller
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18/*
@CrossOrigin 注释在带注释的控制器方法上启用跨源请求
*/
public class ScheduleController
{
private ScheduleService scheduleService;
public R showList(int pageSize, int currentPage){
PageBean<Schedule> pageBean = scheduleService.findByPage(pageSize,currentPage);
return R.ok(pageBean);
}
}service
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
public class ScheduleServiceImpl implements ScheduleService {
private ScheduleMapper scheduleMapper;
/**
* 分页数据查询,返回分页pageBean
*
* @param pageSize
* @param currentPage
* @return
*/
public PageBean<Schedule> findByPage(int pageSize, int currentPage) {
//1.设置分页参数
PageHelper.startPage(currentPage,pageSize);
//2.数据库查询
List<Schedule> list = scheduleMapper.queryPage();
//3.结果获取
PageInfo<Schedule> pageInfo = new PageInfo<>(list);
//4.pageBean封装
PageBean<Schedule> pageBean = new PageBean<>(pageInfo.getPageNum(),pageInfo.getPageSize(),pageInfo.getTotal(),pageInfo.getList());
log.info("分页查询结果:{}",pageBean);
return pageBean;
}
}mapper
mapper 接口
1
2
3
4public interface ScheduleMapper {
List<Schedule> queryPage();
}mapperxml 文件
1
2
3
4
5
6
7
8
9
10
11
<!-- namespace等于mapper接口类的全限定名,这样实现对应 -->
<mapper namespace="com.atguigu.mapper.ScheduleMapper">
<select id="queryPage" resultType="schedule">
select * from schedule
</select>
</mapper>
计划添加
controller
1
2
3
4
5
public R saveSchedule({ Schedule schedule)
scheduleService.saveSchedule(schedule);
return R.ok(null);
}service
1
2
3
4
5
6
7
8
9/**
* 保存学习计划
*
* @param schedule
*/
public void saveSchedule(Schedule schedule) {
scheduleMapper.insert(schedule);
}mapper
mapper 接口
1
void insert(Schedule schedule);
mapperxml 文件
1
2
3
4
5<insert id="insert">
insert into schedule (title, completed)
values
(#{title}, #{completed});
</insert>
计划删除
controller
1
2
3
4
public R removeSchedule({ Integer id)
scheduleService.removeById(id);
return R.ok(null); }service
1
2
3
4
5
6
7
8
9/**
* 移除学习计划
*
* @param id
*/
public void removeById(Integer id) {
scheduleMapper.delete(id);
}mapper mapper 接口
1
void delete(Integer id);
mapperxml 文件
1
2
3<delete id="delete">
delete from schedule where id = #{id}
</delete>
计划修改
controller
1
2
3
4
5
public R changeSchedule({ Schedule schedule)
scheduleService.updateSchedule(schedule);
return R.ok(null);
}service
1
2
3
4
5
6
7
8
9/**
* 更新学习计划
*
* @param schedule
*/
public void updateSchedule(Schedule schedule) {
scheduleMapper.update(schedule);
}mapper mapper 接口
1
void update(Schedule schedule);
mapperxml 文件
1
2
3
4<update id="update">
update schedule set title = #{title} , completed = #{completed}
where id = #{id}
</update>
4.3 前后联调
后台项目根路径设计
启动测试即可