- Springboot基础篇
- 快速上手 Springboot
- Springboot入门程序分析
- SpringBoot基础配置
- 整合第三方技术
- 基于Springboot的SSMP整合
一、基础篇
- 基础篇的目标是上手,能够使用 springboot 搭建基于 springboot 的 web 项目进行开发。
1.1 快速上手 Springboot
- SpringBoot 技术由 Pivotal 团队研发制作,功能的话简单概括就是加速 Spring 程序的开发,这个加速要从以下两个方面来说:
- Spring 程序初始搭建过程
- Spring 程序的开发过程
- Spring 程序缺点:
- 依赖设置繁琐:需要在
pom.xml
文件中设置相关依赖,相关依赖项很多。 - 配置繁琐:对每个 SSM 项目,都需要配置
spring.xml
、springmvc.xml
、mybatis-config.xml
文件。
- 依赖设置繁琐:需要在
- Springboot 程序优点:
- 起步依赖:简化依赖配置。
- 自动配置:简化常用工程相关配置。
- 辅助功能:内置服务器等…
1.1.1 Springboot入门程序
下面使用 SpringBoot 技术快速构建一个 SpringMVC 的程序,通过这个过程体会简化二字的含义:
创建新模块
springboot_01_01_quickstart
,选择Spring Initializr
,并配置模块相关基础信息:- 注意:在 idea 中使用 springboot 时,是需要联网的,如果不能正常联网,就会显示一直在加载中。
选择当前模块需要使用的技术集:
开发控制器类。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20package com.f.springboot.controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
/**
* @author fzy
* @date 2024/2/21 14:30
*/
// Rest模式
public class BookController {
public String get() {
System.out.println("Springboot is running...");
return "springboot";
}
}- 入门案例制作的 SpringMVC 的控制器是基于 Restful 风格开发的,当然此处使用原始格式制作 SpringMVC 的程序也是没有问题的,上例中的
@RestController
与@GetMapping
注解是基于 Restful 开发的典型注解。
- 入门案例制作的 SpringMVC 的控制器是基于 Restful 风格开发的,当然此处使用原始格式制作 SpringMVC 的程序也是没有问题的,上例中的
运行自动生成的
Application
类:1
2
3
4
5
6
7
8
9
10
11package com.f.springboot;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22. ____ _ __ _ _
/\\ / ___'_ __ _ _(_)_ __ __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
\\/ ___)| |_)| | | | | || (_| | ) ) ) )
' |____| .__|_| |_|_| |_\__, | / / / /
=========|_|==============|___/=/_/_/_/
:: Spring Boot :: (v3.2.2)
2024-02-21T14:42:52.528+08:00 INFO 11528 --- [ main] com.f.springboot.Application : Starting Application using Java 17.0.8 with PID 11528 (C:\Users\Running Noob\Code Project\Springboot-learning-code\springboot_01_01_quickstart\target\classes started by Running Noob in C:\Users\Running Noob\Code Project\Springboot-learning-code)
2024-02-21T14:42:52.532+08:00 INFO 11528 --- [ main] com.f.springboot.Application : No active profile set, falling back to 1 default profile: "default"
2024-02-21T14:42:53.227+08:00 INFO 11528 --- [ main] o.s.b.w.embedded.tomcat.TomcatWebServer : Tomcat initialized with port 8080 (http)
2024-02-21T14:42:53.230+08:00 INFO 11528 --- [ main] o.a.catalina.core.AprLifecycleListener : Loaded Apache Tomcat Native library [2.0.6] using APR version [1.7.4].
2024-02-21T14:42:53.246+08:00 INFO 11528 --- [ main] o.a.catalina.core.AprLifecycleListener : OpenSSL successfully initialized [OpenSSL 3.0.11 19 Sep 2023]
2024-02-21T14:42:53.254+08:00 INFO 11528 --- [ main] o.apache.catalina.core.StandardService : Starting service [Tomcat]
2024-02-21T14:42:53.254+08:00 INFO 11528 --- [ main] o.apache.catalina.core.StandardEngine : Starting Servlet engine: [Apache Tomcat/10.1.18]
2024-02-21T14:42:53.291+08:00 INFO 11528 --- [ main] o.a.c.c.C.[Tomcat].[localhost].[/] : Initializing Spring embedded WebApplicationContext
2024-02-21T14:42:53.291+08:00 INFO 11528 --- [ main] w.s.c.ServletWebServerApplicationContext : Root WebApplicationContext: initialization completed in 713 ms
2024-02-21T14:42:53.576+08:00 INFO 11528 --- [ main] o.s.b.w.embedded.tomcat.TomcatWebServer : Tomcat started on port 8080 (http) with context path ''
2024-02-21T14:42:53.581+08:00 INFO 11528 --- [ main] com.f.springboot.Application : Started Application in 1.371 seconds (process running for 1.928)
2024-02-21T14:43:57.706+08:00 INFO 11528 --- [nio-8080-exec-1] o.a.c.c.C.[Tomcat].[localhost].[/] : Initializing Spring DispatcherServlet 'dispatcherServlet'
2024-02-21T14:43:57.706+08:00 INFO 11528 --- [nio-8080-exec-1] o.s.web.servlet.DispatcherServlet : Initializing Servlet 'dispatcherServlet'
2024-02-21T14:43:57.707+08:00 INFO 11528 --- [nio-8080-exec-1] o.s.web.servlet.DispatcherServlet : Completed initialization in 1 ms- 从上面控制台的信息可以看到,jdk 版本是 17.0.8,tomcat 端口是 8080,版本是 10.1.18,应用程序根路径为 ‘’。
在浏览器上通过 localhost:8080/books 进行测试。
下面是入门程序的
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
<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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>3.2.2</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.f</groupId>
<artifactId>springboot_01_01_quickstart</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>springboot_01_01_quickstart</name>
<description>springboot_01_01_quickstart</description>
<properties>
<java.version>17</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>- 注意:最简单的 Springboot 项目至少要包含两个基础文件:
- 上面的
pom.xml
文件。 - 自动生成的
Application
类。
- 上面的
- 注意:最简单的 Springboot 项目至少要包含两个基础文件:
通过上面的入门程序,我们不难发现,SpringBoot 程序简直太好写了,几乎什么都没写,功能就有了,这也是 SpringBoot 技术为什么现在这么火的原因,和 Spirng 程序相比,SpringBoot 程序在开发的过程中各个层面均具有优势。
类配置文件 Spring SpringBoot pom文件中的坐标 手工添加 勾选添加 web3.0配置类 手工制作 无 Spring/SpringMVC配置类 手工制作 无 控制器 手工制作 手工制作 一句话总结一下就是能少写就少写,能不写就不写,这就是 SpringBoot 技术给我们带来的好处。
1.1.2 小结
- 开发 SpringBoot 程序可以根据向导进行联网快速制作。
- SpringBoot 程序需要基于 JDK8 以上版本进行制作。
- SpringBoot 程序中需要使用何种功能通过勾选选择技术,也可以手工添加对应的要使用的技术。
- 运行 SpringBoot 程序通过运行自动生成的 Application 程序进行。
1.1.3 ★修改联网URL
Spring Initializr
的默认 URL 为 start.spring.io,是国外的网址,速度较慢,我们可以将其更改为阿里云的地址 Cloud Native App Initializer (aliyun.com) ,加载就会更快。- 阿里为了便于自己开发使用,因此在依赖坐标中添加了一些阿里相关的技术,也是为了推广自己的技术吧,所以在依赖选择列表中,你有了更多的选择。
1.2 ★★★Springboot入门程序分析
1.2.1 parent
对于多个项目,例如
project-a
和project-b
,它们的依赖有可能是重合的,在这种情况下,为了提高依赖的复用性,可以将重合的依赖抽取出来,形成parent
,然后project-a
和project-b
只要使用<parent><parent/>
标签引用parent
,就不需要在引入依赖的时候指定依赖版本号了。在
parent
中,通过<properties><properties/>
标签将依赖版本统一管理。注意:使用
<parent><parent/>
标签只是表示在项目中引入依赖时不需要指定依赖版本号了(因为在parent
中统一指定了),但不代表在项目中不需要引入依赖。例如,在
parent
中指定了aspectj
依赖的版本号:1
2
3
4
5
6
7
8
9...
<aspectj.version>1.9.21</aspectj.version>
...
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>${aspectj.version}</version>
</dependency>
...那么,在项目中引入
aspectj
依赖时,就不需要指定版本号:1
2
3
4
5
6
7
8
9
10
11
12
13
14...
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>3.2.2</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
...
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<!--没有指定version-->
</dependency>
...因为在
parent
中已经指定了。但这并不代表你的项目要引入
aspectj
依赖的时候,只需要<parent><parent/>
中的内容,而不需要<dependency><dependency/>
中的内容。
总之:**
parent
是用来统一依赖版本号,避免出现版本冲突的**。
开发 Springboot 项目需要继承
spring-boot-starter-parent
,1
2
3
4
5
6
7
8
9
10
11
<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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>3.2.2</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
......spring-boot-starter-parent
中定义了若干个依赖管理(坐标版本号),继承parent
模块可以避免多个依赖使用相同技术时出现依赖版本冲突。
1.2.2 starter
SpringBoot 中常见项目名称,定义了当前项目使用的所有依赖坐标,以达到减少依赖配置的目的。
例如,在
spring-boot-starter-web
中,引入了一系列的依赖: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
<project xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd" xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<modelVersion>4.0.0</modelVersion>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<version>3.0.2</version>
......
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
<version>3.0.2</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-json</artifactId>
<version>3.0.2</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-tomcat</artifactId>
<version>3.0.2</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-web</artifactId>
<version>6.0.4</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>6.0.4</version>
<scope>compile</scope>
</dependency>
</dependencies>
</project>这些依赖是我们开发 JavaWeb 项目所需要的,我们现在只要引入
spring-boot-starter-web
依赖,就能使用这些依赖了,就是 maven 中依赖传递的概念。Springboot 中有一系列含有
starter
名称的依赖,每个starter
根据功能不同,通常包含多个依赖坐标,用于简化配置。
1.2.3 parent和starter的区别
parent
是用来统一依赖版本号,避免出现版本冲突的,它只是指定了依赖版本号,到底要不要使用依赖,是要在项目的pom.xml
中配置的。starter
是预先引入了一些依赖,只要项目的pom.xml
中引入了该starter
依赖,就等于引入了该starter
中预先引入的依赖,就等于是在项目中一定会有这些依赖,是依赖传递的概念。在实际开发中:
- 使用任意坐标时,仅书写 GAV 中的 G 和 A,V 由 SpringBoot 提供(即前面所说的
parent
),除非 SpringBoot 未提供对应版本 V。 - 如果发生坐标错误,再指定 Version (要小心版本冲突)。
- 使用任意坐标时,仅书写 GAV 中的 G 和 A,V 由 SpringBoot 提供(即前面所说的
1.2.4 引导类
引导类是 springboot 自动生成的:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17package com.f.springboot;
import com.f.springboot.controller.BookController;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ConfigurableApplicationContext;
public class Springboot0102QuickstartApplication {
public static void main(String[] args) {
// SpringApplication.run的返回值就是ApplicationContext,就是一个spring容器
// 所以下面这行代码就是启动了一个spring容器
ConfigurableApplicationContext context = SpringApplication.run(Springboot0102QuickstartApplication.class, args);
BookController bookController = context.getBean(BookController.class);
System.out.println(bookController);
}
}引导类是整个 springboot 程序的入口,运行
main
方法就可以启动项目。
1.2.5 内嵌tomcat
springboot 是如何内嵌 tomcat 的?
在
spring-boot-starter-web
依赖中,有一个spring-boot-starter-tomcat
依赖,该依赖含有 tomcat 核心依赖tomcat-embed-core
,因此,当启动项目时,相当于在 spring 容器中托管了 tomcat 服务器对象,然后该 tomcat 服务器对象提供 web 服务。内嵌 Tomcat 的工作原理是将 Tomcat 服务器作为对象运行,并将该对象交给 Spring 容器管理。
在
1.2.2 starter
小节的配置文件中可以看到,spring-boot-starter-web
依赖中有一个spring-boot-starter-tomcat
依赖。然后,在
spring-boot-starter-tomcat
依赖中,含有tomcat-embed-core
依赖。1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
<project xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd" xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<modelVersion>4.0.0</modelVersion>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-tomcat</artifactId>
<version>3.0.2</version>
......
<dependency>
<groupId>org.apache.tomcat.embed</groupId>
<artifactId>tomcat-embed-core</artifactId>
<version>10.1.5</version>
<scope>compile</scope>
<exclusions>
<exclusion>
<artifactId>tomcat-annotations-api</artifactId>
<groupId>org.apache.tomcat</groupId>
</exclusion>
</exclusions>
</dependency>
......
1.3 ★SpringBoot基础配置
1.3.1 属性配置
springboot 项目的默认配置文件就是
resources
目录下的application.properties
,是自动生成的。通过配置文件
application.properties
就可以修改默认的配置,先找个简单的配置下手:当前访问 tomcat 的默认端口是 8080,将其修改为 80 端口:
1
2# 应用服务 WEB 访问端口
server.port=80- 运行发现没问题。
事实上,springboot 所有的配置都可以写在这一个文件中,但那样会使得
application.properties
文件变得臃肿,而且也不利于维护,所以我们会使用多个配置文件来对 springboot 项目进行配置。springboot 项目的一些其他配置:
1
2# 日志级别
logging.level.root=debug- 具体都有哪些配置,可以参考:Common Application Properties (spring.io)
1.3.2 配置文件分类
- 为了避免将 springboot 项目所有的配置都写在同一个文件中,SpringBoot 除了支持
properties
格式的配置文件,还支持另外两种格式的配置文件。分别如下:yml
格式(主流格式)yaml
格式
1.3.2.1 properties格式(传统格式)
1 | server.port=80 |
1.3.2.2 yml格式(主流格式)
1 | server: |
1.3.2.3 yaml格式
1 | server: |
仔细看会发现
yml
格式和yaml
格式除了文件名后缀不一样,格式是完全一样的,其实yml
和yaml
文件格式就是一模一样的,只是文件后缀不同,所以可以合并成一种格式来看。以后基本上都是用
yml
格式的,本课程后面的所有知识都是基于yml
格式来制作的,以后在企业开发过程中用这个格式的机会也最多,一定要重点掌握。另外:配置文件的优先级为
properties
(最高)>yml
>yaml
(最低)不同配置文件中的相同配置,按照加载优先级相互覆盖,不同配置文件中不同配置全部保留。
1.3.3 ★yaml文件
- yaml 是一个可读性高,用来表达数据序列化的格式。其具有容易阅读、容易与脚本语言交互、以数据为核心,重数据轻格式的特点。
- yaml 常见的文件扩展名有两种:
.yml
(主流).yaml
- yaml 常见的文件扩展名有两种:
1.3.3.1 yaml语法规则
yaml 语法规则:
- 大小写敏感
- 属性层级关系使用多行描述,属性结尾使用冒号结束
- 使用缩进表示层级关系,同层级左侧对齐,只允许使用空格(不允许使用 Tab 键)
- 属性值前面添加空格(属性名与属性值之间使用 “冒号 + 空格” 作为分隔)
#
号表示注释
核心的一条规则要记住,数据前面要加空格,与冒号隔开。
1
2
3
4
5
6
7boolean: TRUE # TRUE,true,True,FALSE,false,False均可
float: 3.14 # 6.8523015e+5 #支持科学计数法
int: 123 # 0b1010_0111_0100_1010_1110 #支持二进制、八进制、十六进制
string: HelloWorld # 字符串可以直接书写
string2: "Hello World" # 可以使用双引号包裹特殊字符,在双引号中的转义字符是会被解析的
date: 2018-02-17 # 日期必须使用yyyy-MM-dd格式
datetime: 2018-02-17T15:02:31+08:00 # 时间和日期之间使用T连接,最后使用+代表时区此外,yaml 格式中也可以表示数组,在属性名书写位置的下方使用减号作为数据开始符号,每行书写一个数据,减号与数据间空格分隔:
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
28subject:
- Java
- 前端
- 大数据
enterprise:
name: itcast
age: 16
subject:
- Java
- 前端
- 大数据
likes1: [sing,dance] #数组书写缩略格式
likes2:
- sing
- dance
users1: #对象数组格式一
- name: Tom
age: 4
- name: Jerry
age: 5
users2: #对象数组格式二
-
name: Tom
age: 4
-
name: Jerry
age: 5
users3: [{ name:Tom , age:4 },{ name:Jerry , age:5 }] #对象数组缩略格式
1.3.3.2 读取yaml单一属性数据
yaml 中保存的单个数据,可以使用 Spring 中的注解直接读取,使用
@Value
可以读取单个数据。- 属性名引用方式:
@Value("${一级属性名.二级属性名......}")
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
52package com.f.springboot.controller;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
/**
* @author fzy
* @date 2024/2/21 22:11
*/
public class BookController {
// 读取单一属性
// string: HelloWorld
private String str;
/**
* 读取属性的属性
* enterprise:
* name: itcast
* age: 16
* subject:
* - Java
* - 前端
* - 大数据
*/
private String enterpriseName;
/**
* 读取数组数据
* likes2:
* - sing
* - dance
*/
private String like;
public String get() {
return "springboot...";
}
// 读取yaml数据中的单一数据
public String getYamlSingle() {
return str + "<br/>" + enterpriseName + "<br/>" + like;
}
}- 注意:使用
@Value
注解时,要将该注解写在某一个指定的 Spring 管理的 bean 的属性名上方。
- 属性名引用方式:
yaml 文件中还可以引用变量,例如:
1
2
3
4
5center:
dataDir: /usr/local/fire/data
tmpDir: /usr/local/fire/tmp
logDir: /usr/local/fire/log
msgDir: /usr/local/fire/msgDir中有重合部分:
/usr/local/fire
。可以修改为下面的表示形式:
1
2
3
4
5
6baseDir: /usr/local/fire
center:
dataDir: ${baseDir}/data # 使用${变量名}的形式引用变量
tmpDir: ${baseDir}/tmp
logDir: ${baseDir}/log
msgDir: ${baseDir}/msgDir
1.3.3.3 读取yaml全部属性数据
读取单一数据可以解决读取数据的问题,但是如果在 yaml 文件中的数据量过大,那在 java 文件中要定义的变量将会很多。
为此,SpringBoot 提供了一个对象,能够把所有的数据都封装到这一个对象中,这个对象叫做
Environment
,使用自动装配注解@Autowired
可以将 yaml 文件中所有的数据封装到这个对象中: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
40package com.f.springboot.controller;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.core.env.Environment;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
/**
* @author fzy
* @date 2024/2/21 22:11
*/
public class BookController {
......
// 使用自动装配将所有的数据封装到一个Environment对象中
private Environment env;
public String get() {
return "springboot...";
}
// 读取yaml数据中的单一数据
public String getYamlSingle() {
return str + "<br/>" + enterpriseName + "<br/>" + like + "<br/>" + dir;
}
// 读取yaml数据中的所有数据
public String getYamlAll() {
// 使用getProperty方法获取数据
return env.getProperty("enterprise.name");
}
}- 数据封装到了
Environment
对象中,获取属性时,通过Environment
的接口方法进行,具体方法为getProperties(String)
,参数填写属性名即可。
- 数据封装到了
1.3.3.4 读取yaml对象数据(主流)
读取单一属性数据过于繁琐,需要定义对应数量的变量;读取全部数据又过于封装,要将所有数据封装在
Environment
对象中,每次取数据都需要调用getProperties()
方法。由于 Java 是一个面向对象的语言,很多情况下,我们会将一组数据封装成一个对象。因此,SpringBoot 也提供了可以将一组 yaml 数据封装在一个 Java 对象中的操作。例如,如果我们要将下面的配置数据封装到一个 Java 对象中:
1
2
3
4
5datasource:
driver: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://localhost:3306/springboot
username: root
password: root首先创建一个对象类,将对象类实例化,并将该对象纳入 Spring 容器管理,也就是定义一个 bean。
然后使用注解
@ConfigurationProperties
指定该对象加载 yaml 中哪一组配置信息。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
75package com.f.springboot.pojo;
/**
* @author fzy
* @date 2024/2/22 15:44
*/
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
/**
* 1. 定义数据模型封装yaml文件中对应的数据
* 2. 将其定义为spring容器管理的bean
* 3. 指定要加载yaml文件中的什么数据 @ConfigurationProperties
*/
public class DataSource {
private String driver;
private String url;
private String username;
private String password;
public DataSource() {
}
public DataSource(String driver, String url, String username, String password) {
this.driver = driver;
this.url = url;
this.username = username;
this.password = password;
}
public String toString() {
return "DataSource{" +
"driver='" + driver + '\'' +
", url='" + url + '\'' +
", username='" + username + '\'' +
", password='" + password + '\'' +
'}';
}
public String getDriver() {
return driver;
}
public void setDriver(String driver) {
this.driver = driver;
}
public String getUrl() {
return url;
}
public void setUrl(String url) {
this.url = url;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
}@ConfigurationProperties
必须指明数据前缀是什么,这样该前缀下的所有属性就封装到这个对象中。注意:数据属性名要与对象的变量名一一对应,否则无法封装。
最后使用
@Autowired
自动装配对象:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25package com.f.springboot.controller;
import com.f.springboot.pojo.DataSource;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
/**
* @author fzy
* @date 2024/2/22 15:53
*/
public class YamlController {
// 4. 使用@Autowired自动装配
private DataSource dataSource;
public DataSource getDataSource() {
return dataSource;
}
}
1.4 整合第三方技术
- springboot 整合第三方技术的流程都大同小异,主要包括以下几步:
- 在 Spring Initializr 中选择要整合的第三方技术的技术集。
- 如果没有可勾选的第三方技术集,可以在项目初始化后,在
pom.xml
文件中手工引入dependency
。 - 主要是导入对应的 “
starter
”。
- 如果没有可勾选的第三方技术集,可以在项目初始化后,在
- 对技术集进行相应的配置,设置配置文件,例如
application.yml
。 - 进行功能开发和测试。
- 在 Spring Initializr 中选择要整合的第三方技术的技术集。
1.4.1 整合Junit
springboot 整合 junit 的核心注解:
@SpringBootTest
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19package com.f.springboot;
import com.f.springboot.dao.BookDao;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
class Springboot03JunitApplicationTests {
// 1.注入要测试的对象
private BookDao bookDao;
void contextLoads() {
// 2.执行要测试的对象的对应方法
bookDao.save();
}
}@SpringBootTest
有一个classes
属性,用于设置 springboot 启动类。1
2
3
4
5
6
7
8
9
10
11
12package com.f.springboot;
import com.f.springboot.dao.BookDao;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
// 通过classes属性指定要测试的springboot启动类
class Springboot03JunitApplicationTests {
......
}- 如果测试类在 SpringBoot 启动类的包或子包中,则可以省略启动类的设置,也就是省略
classes
的设定。
- 如果测试类在 SpringBoot 启动类的包或子包中,则可以省略启动类的设置,也就是省略
1.4.2 整合Mybatis
springboot 整合 Mybatis 的步骤:
创建新模块
springboot_04_mybatis
,选择 Spring 初始化,并配置模块相关基础信息:选择当前模块需要使用的技术集,既然是整合 Mybatis,那就选择 Mybatis 相关的技术集(MyBatis、MySQL):
观察项目的
pom.xml
文件,可以发现有 mybatis 和 MySQL 的相关依赖: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
<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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.f</groupId>
<artifactId>springboot_04_mybatis</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>springboot_04_mybatis</name>
<description>springboot_04_mybatis</description>
<properties>
<java.version>17</java.version>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<spring-boot.version>3.0.2</spring-boot.version>
</properties>
<dependencies>
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>3.0.0</version>
</dependency>
<dependency>
<groupId>com.mysql</groupId>
<artifactId>mysql-connector-j</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
......
</project>
在
application.yml
文件中设置数据源参数:1
2
3
4
5
6
7
8
9
10
11
12
13mybatis:
#指定Mybatis的Mapper文件
mapper-locations: classpath:com/f/springboot/mapper/*.xml
#指定Mybatis的实体目录
type-aliases-package: com.f.springboot.pojo
# 配置数据库信息
spring:
datasource:
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://localhost:3306/springboot
username: root
password: root在 springboot 数据库中创建
t_book
表。创建实体 Bean:
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
64package com.f.springboot.pojo;
/**
* @author fzy
* @date 2024/2/22 21:41
*/
public class Book {
private Integer id;
private String type;
private String name;
private String description;
public Book() {
}
public Book(Integer id, String type, String name, String description) {
this.id = id;
this.type = type;
this.name = name;
this.description = description;
}
public String toString() {
return "Book{" +
"id=" + id +
", type='" + type + '\'' +
", name='" + name + '\'' +
", description='" + description + '\'' +
'}';
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getType() {
return type;
}
public void setType(String type) {
this.type = type;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
}定义数据访问层接口与映射配置:
1
2
3
4
5
6
7
8
9
10
11
12
13
14package com.f.springboot.mapper;
import com.f.springboot.pojo.Book;
import org.springframework.stereotype.Repository;
/**
* @author fzy
* @date 2024/2/22 21:43
*/
public interface BookMapper {
// 根据id查询图书信息
Book getById(Integer id);
}1
2
3
4
5
6
7
8
9
10
11
12
13
<mapper namespace="com.f.springboot.mapper.BookMapper">
<select id="getById" resultType="Book">
SELECT id, type, name, description
FROM t_book
<where>
id = #{id}
</where>
</select>
</mapper>在引导类中添加
@MapperScan
注解,指定要变成实现类的接口所在的包,然后包下面的所有接口在编译之后都会生成相应的实现类:1
2
3
4
5
6
7
8
9
10
11
12
13package com.f.springboot;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
public class Springboot04MybatisApplication {
public static void main(String[] args) {
SpringApplication.run(Springboot04MybatisApplication.class, args);
}
}在测试类中注入
mapper
接口,测试功能:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19package com.f.springboot;
import com.f.springboot.mapper.BookMapper;
import com.f.springboot.pojo.Book;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
class Springboot04MybatisApplicationTests {
private BookMapper bookMapper;
void contextLoads() {
Book book = bookMapper.getById(1);
System.out.println(book);
}
}
★@Mapper、@MapperScan、@Repository
在上面整合 Mybatis 的例子中,需要用到
@MapperScan
和@Repository
注解,才能动态生成Mapper
接口的实现类,但其实只用一个@Mapper
注解也能达到类似的效果,其中的区别如下:@Repository
是标注在mapper
包的接口上,作用是将接口的一个实现类交给 Spring 管理,但是使用这个注解的前提是必须在引导类上添加@MapperScan("Mapper接口层路径")
的注解。这个
@Repository
完全可以省略不写,也可以实现自动注入,但是在 IDEA 中会存在一个红色的波浪线。所以最好还是在接口上加上这个注解,例如上面例子中的:1
2
3
4
5
public interface BookMapper {
// 根据id查询图书信息
Book getById(Integer id);
}1
2
3
4
5
6
7
public class Springboot04MybatisApplication {
public static void main(String[] args) {
SpringApplication.run(Springboot04MybatisApplication.class, args);
}
}@Mapper
这个注解一般也是使用在mapper
层的接口上,相当于一个mapper.xml
文件,它的作用就是将接口生成一个动态代理类。加入@Mapper
注解的目的就是为了不再写mapper.xml
映射文件。这个注解就是用来代替mapper.xml
文件的(Mybatis 的全注解式开发)。使用
@mapper
后,不需要在 spring 配置中设置扫描地址,通过mapper.xml
里面的namespace
属性对应相关的mapper
类,spring 就可以动态的生成动态代理类。1
2
3
4
5
public interface BookMapper {
// 根据id查询图书信息
Book getById(Integer id);
}- 当我们的一个项目中存在多个
mapper
层接口的时候,我们需要对每个接口类都写上@Mapper
注解,非常的麻烦,此时可以使用@MapperScan
注解来解决这个问题。让这个接口进行一次性的注入,不需要再写@Mapper
注解。
- 当我们的一个项目中存在多个
总之,
@Mapper
注解相当于是@Reponsitory
注解和@MapperScan
注解的和,会自动的进行配置加载。@MapperScan
注解多个包,@Mapper
只能把当前接口类进行动态代理。在实际开发中,如何使用
@Mapper
、@MapperSacn
、@Repository
注解:- 在 SpringBoot 的引导类上给定
@MapperSacn
注解,此时mapper
层的接口可以省略@Mapper
注解,@Repository
注解可写可不写,最好还是写上。 - 当使用
@Mapper
注解的时候,可以省略@MapperSacn
以及@Repository
。
建议以后在使用的时候,在启动类上给定
@MapperScan("mapper层接口所在的包路径")
。在mapper
层接口上不写@Mapper
注解,写上@Repository
即可。- 在 SpringBoot 的引导类上给定
1.4.3 整合Druid
springboot 整合 Druid 的步骤:
创建新模块
springboot_05_druid
,选择 Spring 初始化,并配置模块相关基础信息:选择当前模块需要使用的技术集,既然是整合 Druid,那就选择 Druid 相关的技术集(MyBatis、MySQL、Druid),但是发现没有 Druid 相关的技术集可以勾选,那就在项目初始化后,在
pom.xml
文件中手动引入 Druid 相关依赖druid-spring-boot-starter
: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
<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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.f</groupId>
<artifactId>springboot_05_druid</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>springboot_05_druid</name>
<description>springboot_05_druid</description>
<properties>
<java.version>17</java.version>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<spring-boot.version>3.0.2</spring-boot.version>
</properties>
<dependencies>
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>3.0.0</version>
</dependency>
<!--druid-spring-boot-starter依赖-->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid-spring-boot-starter</artifactId>
<version>1.2.19</version>
</dependency>
<dependency>
<groupId>com.mysql</groupId>
<artifactId>mysql-connector-j</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
......
</project>在
application.yml
文件中进行相应配置:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25mybatis:
#指定Mybatis的Mapper文件
mapper-locations: classpath:com/f/springboot/mapper/*.xml
#指定Mybatis的实体目录
type-aliases-package: com.f.springboot.pojo
# 配置数据库信息
# 配法1
#spring:
# datasource:
# driver-class-name: com.mysql.cj.jdbc.Driver
# url: jdbc:mysql://localhost:3306/springboot
# username: root
# password: root
# type: com.alibaba.druid.pool.DruidDataSource
# 配法2(更推荐)
spring:
datasource:
druid:
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://localhost:3306/springboot
username: root
password: root接下来的步骤类似于
1.4.2 整合Mybatis
小节,就不做过多赘述了。
1.5 ★★★基于Springboot的SSMP整合
- 案例实现方案分析
实体类开发————使用Lombok
快速制作实体类
Dao开发————整合MyBatisPlus,制作数据层测试类
Service开发————基于MyBatisPlus进行增量开发,制作业务层测试类
Controller开发————基于Restful开发,使用PostMan测试接口功能
Controller开发————前后端开发协议制作
页面开发————基于VUE+ElementUI制作,前后端联调,页面数据处理,页面消息处理
列表、新增、修改、删除、分页、查询
项目异常处理
按条件查询————页面功能调整、Controller修正功能、Service修正功能- SSMP案例制作流程解析
先开发基础CRUD功能,做一层测一层
调通页面,确认异步提交成功后,制作所有功能
添加分页功能与查询功能
1.5.1 前期准备
创建新模块
springboot_06_ssmp
,选择 Spring 初始化,并配置模块相关基础信息:选择当前模块需要使用的技术集,包括 Spring Web、MySQL Driver,在项目初始化后配置
pom.xml
文件,手动添加mybatis-plus
和druid
的boot-starter
依赖: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
<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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.f</groupId>
<artifactId>springboot_06_ssmp</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>springboot_06_ssmp</name>
<description>springboot_06_ssmp</description>
<properties>
<java.version>17</java.version>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<spring-boot.version>3.0.2</spring-boot.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>com.mysql</groupId>
<artifactId>mysql-connector-j</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>3.5.3</version>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid-spring-boot-starter</artifactId>
<version>1.2.19</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-dependencies</artifactId>
<version>${spring-boot.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.8.1</version>
<configuration>
<source>17</source>
<target>17</target>
<encoding>UTF-8</encoding>
</configuration>
</plugin>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<version>${spring-boot.version}</version>
<configuration>
<mainClass>com.f.springboot.Springboot06SsmpApplication</mainClass>
<skip>true</skip>
</configuration>
<executions>
<execution>
<id>repackage</id>
<goals>
<goal>repackage</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>- 手动添加依赖的原因是:在
spring-boot-dependencies
中没有对mybatis-plus
和druid
的boot-starter
依赖的版本号进行维护。
- 手动添加依赖的原因是:在
将
application.properties
配置文件改为application.yml
格式,配置端口号:1
2
3# 应用服务 WEB 访问端口
server:
port: 80在 springboot 数据库中创建
t_book
表:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24DROP TABLE IF EXISTS `t_book`;
CREATE TABLE `t_book` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`type` varchar(20) DEFAULT NULL,
`name` varchar(50) DEFAULT NULL,
`description` varchar(255) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8;
-- ----------------------------
-- Records of t_book
-- ----------------------------
INSERT INTO `t_book` VALUES ('1', '计算机理论', 'Spring实战第5版', 'Spring入门经典教程,深入理解Spring原理技术内幕');
INSERT INTO `t_book` VALUES ('2', '计算机理论', 'Spring 5核心原理与30个类手写实战', '十年沉淀之作,写Spring精华思想');
INSERT INTO `t_book` VALUES ('3', '计算机理论', 'Spring 5设计模式', '深入Spring源码剖析Spring源码中蕴含的10大设计模式');
INSERT INTO `t_book` VALUES ('4', '计算机理论', 'Spring MVC+ MyBatis开发从入门到项目实战', '全方位解析面向Web应用的轻量级框架,带你成为Spring MVC开发高手');
INSERT INTO `t_book` VALUES ('5', '计算机理论', '轻量级Java Web企业应用实战', '源码级剖析Spring框架,适合已掌握Java基础的读者');
INSERT INTO `t_book` VALUES ('6', '计算机理论', 'Java核心技术卷|基础知识(原书第11版)', 'Core Java第11版,Jolt大奖获奖作品,针对Java SE9、10、 11全面更新');
INSERT INTO `t_book` VALUES ('7', '计算机理论', '深入理解Java虚拟机', '5个维度全面剖析JVM,面试知识点全覆盖');
INSERT INTO `t_book` VALUES ('8', '计算机理论', 'Java编程思想(第4版)', 'Java学习必读经典殿堂级著作!赢得了全球程序员的广泛赞誉');
INSERT INTO `t_book` VALUES ('9', '计算机理论', '零基础学Java (全彩版)', '零基础自学编程的入门]图书,由浅入深,详解Java语言的编程思想和核心技术');
INSERT INTO `t_book` VALUES ('10', '市场营销', '直播就该这么做:主播高效沟通实战指南', '李子柒、李佳琦、薇娅成长为网红的秘密都在书中');
INSERT INTO `t_book` VALUES ('11', '市场营销', '直播销讲实战一本通', '和秋叶一起学系列网络营销书籍');
INSERT INTO `t_book` VALUES ('12', '市场营销', '直播带货:淘宝、天猫直播从新手到高手', '一本教你如何玩转直播的书, 10堂课轻松实现带货月入3W+');
1.5.2 开发实体类(使用Lombok)
对实体类进行开发,但是我们可以使用
Lombok
快速制作实体类:Lombok
是一个 Java 类库,提供了一组注解,用于简化 pojo 实体类开发。使用
Lombok
之前,需要引入它的依赖:1
2
3
4<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>在
spring-boot-dependencies
中,已经维护了lombok
的版本号。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20package com.f.springboot.pojo;
import lombok.*;
/**
* @author fzy
* @date 2024/2/27 20:30
*/
public class Book {
private Integer id;
private String type;
private String name;
private String description;
}其实还有一种更简便的写法:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15package com.f.springboot.pojo;
import lombok.*;
/**
* @author fzy
* @date 2024/2/27 20:30
*/
public class Book {
private Integer id;
private String type;
private String name;
private String description;
}@Data
为当前实体类在编译期设置对应的get/set
方法,toString
方法,hashCode
方法,equals
方法等
1.5.3 数据层DAO开发
在
application.yml
配置文件中对数据源和 mybatis-plus 进行配置:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19# 应用服务 WEB 访问端口
server:
port: 80
# 数据源配置
spring:
datasource:
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://localhost:3306/springboot
username: root
password: root
type: com.alibaba.druid.pool.DruidDataSource
# mybatis-plus配置
mybatis-plus:
global-config:
db-config:
table-prefix: t_
id-type: auto # 使用数据库默认的自增策略定义数据访问层接口,继承
BaseMapper
接口:1
2
3
4
5
6
7
8
9
10
11
12
13
14package com.f.springboot.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.f.springboot.pojo.Book;
import org.springframework.stereotype.Repository;
/**
* @author fzy
* @date 2024/2/27 20:46
*/
public interface BookMapper extends BaseMapper<Book> {
// 可以根据需要自己再添加复杂的sql语句接口,复杂的sql语句写在xml文件中
}mybatis-plus
已经预置了一些 sql 语句,进行测试: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
56package com.f.springboot.mapper;
import com.f.springboot.pojo.Book;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import java.util.List;
/**
* @author fzy
* @date 2024/2/27 20:50
*/
public class BookMapperTest {
private BookMapper bookMapper;
public void testGetById() {
Book book = bookMapper.selectById(1);
System.out.println(book);
}
public void testGetAll() {
List<Book> books = bookMapper.selectList(null);
books.forEach(book -> {
System.out.println(book);
});
}
public void testInsert() {
Book book = new Book();
book.setType("测试");
book.setName("测试");
book.setDescription("测试");
bookMapper.insert(book);
}
public void testDeleteById() {
bookMapper.deleteById(1);
}
public void testUpdate() {
Book book = new Book();
book.setId(2);
book.setType("测试");
book.setName("测试");
book.setDescription("测试");
bookMapper.updateById(book);
}
}为了看到
mybatis-plus
的执行过程,要开启Mybatis-Plus
运行日志,在application.yml
文件中进行配置(只需要在最后加一行配置log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
):1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21# 应用服务 WEB 访问端口
server:
port: 80
# 数据源配置
spring:
datasource:
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://localhost:3306/springboot
username: root
password: root
type: com.alibaba.druid.pool.DruidDataSource
# mybatis-plus配置
mybatis-plus:
global-config:
db-config:
table-prefix: t_
id-type: auto # 使用数据库默认的自增策略
configuration:
log-impl: org.apache.ibatis.logging.stdout.StdOutImplmybatis-plus
还具有分页功能,使用分页功能需要设定分页对象IPage
以及使用MyBatis-Plus
拦截器,这里不做详细描述,看视频P37
。mybatis-plus
还具有条件查询功能,需要在QueryWrapper
类中指定条件,然后将QueryWrapper
对象作为参数传给select
方法:1
2
3
4
5
6
7
8
9
10
11
12
public void testGetByCondition() {
QueryWrapper<Book> wrapper = new QueryWrapper<>();
// 按条件查询,在wrapper中给定条件
// 查询那些name列中含有Spring的数据
String name = "Spring";
wrapper.like(name != null, "name", name); // 只有当"name != null"时才会带上这个条件
List<Book> books = bookMapper.selectList(wrapper);
books.forEach(book -> {
System.out.println(book);
});
}
1.5.4 业务层Service开发
Service
层接口定义与DAO
层接口定义具有较大区别,不要混用:- 业务层接口定义关注的是业务的名称。
- 数据层接口定义关注的是数据库相关的操作。
定义业务层接口:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19package com.f.springboot.service;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.f.springboot.pojo.Book;
import java.util.List;
/**
* @author fzy
* @date 2024/2/27 22:25
*/
public interface BookService {
Boolean save(Book book);
Boolean update(Book book);
Boolean delete(Integer id);
Book getById(Integer id);
List<Book> getAll();
IPage<Book> getPage(Integer currentPage, Integer pageSize);
}- 数据层考虑影响了多少条数据,业务层考虑业务是否完成。
- 所以 dml 操作的返回值都是
Boolean
类型,而不是Integer
类型。
- 所以 dml 操作的返回值都是
- 数据层考虑影响了多少条数据,业务层考虑业务是否完成。
业务层接口实现类:
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
52package com.f.springboot.service.impl;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.f.springboot.mapper.BookMapper;
import com.f.springboot.pojo.Book;
import com.f.springboot.service.BookService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.List;
/**
* @author fzy
* @date 2024/2/27 22:26
*/
public class BookServiceImpl implements BookService {
private BookMapper bookMapper;
public Boolean save(Book book) {
return bookMapper.insert(book) > 0;
}
public Boolean update(Book book) {
return bookMapper.updateById(book) > 0;
}
public Boolean delete(Integer id) {
return bookMapper.deleteById(id) > 0;
}
public Book getById(Integer id) {
return bookMapper.selectById(id);
}
public List<Book> getAll() {
return bookMapper.selectList(null);
}
public IPage<Book> getPage(Integer currentPage, Integer pageSize) {
IPage page = new Page(currentPage, pageSize);
return bookMapper.selectPage(page, null);
}
}业务层测试类:
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
67package com.f.springboot.service;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.f.springboot.pojo.Book;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import java.util.List;
/**
* @author fzy
* @date 2024/2/28 9:41
*/
public class BookServiceTest {
private BookService bookService;
public void testGetById() {
Book book = bookService.getById(2);
System.out.println(book);
}
public void testGetAll() {
List<Book> books = bookService.getAll();
books.forEach(book -> {
System.out.println(book);
});
}
public void testSave() {
Book book = new Book();
book.setType("测试");
book.setName("测试");
book.setDescription("测试");
bookService.save(book);
}
public void testDeleteById() {
bookService.delete(1);
}
public void testUpdate() {
Book book = new Book();
book.setId(2);
book.setType("测试");
book.setName("测试");
book.setDescription("测试");
bookService.update(book);
}
public void testGetPage() {
IPage<Book> page = bookService.getPage(2, 5);
System.out.println(page.getCurrent());
System.out.println(page.getSize());
System.out.println(page.getPages());
System.out.println(page.getTotal());
System.out.println(page.getRecords());
}
}如果对项目中的另外一张表
t_user
进行操作,操作方法和t_book
基本相同,那就意味着新建的UserService
接口和已有的BookService
接口重合度很大,等于是在写重复的代码。为此,
MyBatis-Plus
提供有业务层通用接口(ISerivce<T>
)与业务层通用实现类(ServiceImpl<M,T>
),来帮助我们简化开发,减少重复代码:1
2
3
4
5
6
7
8
9
10
11package com.f.springboot.service;
import com.baomidou.mybatisplus.extension.service.IService;
import com.f.springboot.pojo.Book;
/**
* @author fzy
* @date 2024/2/28 10:06
*/
public interface IBookService extends IService<Book> {
}1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16package com.f.springboot.service.impl;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.f.springboot.mapper.BookMapper;
import com.f.springboot.pojo.Book;
import com.f.springboot.service.IBookService;
import org.springframework.stereotype.Service;
/**
* @author fzy
* @date 2024/2/28 10:09
*/
public class BookServiceImpl extends ServiceImpl<BookMapper, Book> implements IBookService {
// 可以根据需要自己再添加业务方法
}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
69package com.f.springboot.service;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.f.springboot.pojo.Book;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import java.util.List;
/**
* @author fzy
* @date 2024/2/28 10:12
*/
public class IBookServiceTest {
private IBookService bookService;
public void testGetById() {
Book book = bookService.getById(2);
System.out.println(book);
}
public void testGetAll() {
List<Book> books = bookService.list();
books.forEach(book -> {
System.out.println(book);
});
}
public void testSave() {
Book book = new Book();
book.setType("测试");
book.setName("测试");
book.setDescription("测试");
bookService.save(book);
}
public void testDeleteById() {
bookService.removeById(13);
}
public void testUpdate() {
Book book = new Book();
book.setId(3);
book.setType("测试");
book.setName("测试");
book.setDescription("测试");
bookService.updateById(book);
}
public void testGetPage() {
IPage<Book> p = new Page<>(2,5);
IPage<Book> page = bookService.page(p);
System.out.println(page.getCurrent());
System.out.println(page.getSize());
System.out.println(page.getPages());
System.out.println(page.getTotal());
System.out.println(page.getRecords());
}
}- 注意:在通用类基础上做功能重载或功能追加,重载时不要覆盖原始操作,避免原始提供的功能丢失。
1.5.5 表现层Controller开发
- 基于 Restful 风格进行开发,并使用 PostMan 测试接口功能。
表现层实现类
BookController
: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
57package com.f.springboot.controller;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.f.springboot.pojo.Book;
import com.f.springboot.service.IBookService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import java.util.List;
/**
* @author fzy
* @date 2024/2/28 10:32
*/
public class BookController {
private IBookService bookService;
// 查所有
public List<Book> getAll() {
return bookService.list();
}
// 根据id查询
public Book getById( { Integer id)
return bookService.getById(id);
}
// 分页查询
public List<Book> getByPage( Integer currentPage,
{ Integer pageSize)
IPage page = new Page(currentPage, pageSize);
bookService.page(page);
return page.getRecords();
}
public Boolean save( { Book book)
return bookService.save(book);
}
public Boolean delete( { Integer id)
return bookService.removeById(id);
}
public Boolean update( { Book book)
return bookService.updateById(book);
}
}运行自动生成的
Application
类,启动服务器:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15package com.f.springboot;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
public class Springboot06SsmpApplication {
public static void main(String[] args) {
SpringApplication.run(Springboot06SsmpApplication.class, args);
}
}使用 PostMan 进行测试,这里以保存业务为例:
目前来看,
BookController
中方法的返回结果有以下几种:Boolean
类型、单条json
数据、多条json
数据,json
数组:
那在数据返回前端时,前端程序员要对不同的类型做不同的操作,是比较麻烦的,所以我们要统一数据格式。
我们希望后端返回给前端的数据类型统一为:
flag
表示此次操作是否成功。data
为BookController
中方法的返回结果。
所以我们要设计表现层返回结果的模型类,用于后端与前端进行数据格式统一,也称为“前后端数据协议”。
表现层返回结果的模型类:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25package com.f.springboot.controller.utils;
import lombok.Data;
/**
* @author fzy
* @date 2024/2/28 14:09
*/
public class Result {
private Boolean flag; // 表示操作是否成功
private Object data; // 后端返回的数据
public Result() {
}
public Result(Boolean flag) {
this.flag = flag;
}
public Result(Boolean flag, Object data) {
this.flag = flag;
this.data = data;
}
}有了这个类,我们就可以对
BookController
进行修改: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
60package com.f.springboot.controller;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.f.springboot.controller.utils.Result;
import com.f.springboot.pojo.Book;
import com.f.springboot.service.IBookService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
/**
* @author fzy
* @date 2024/2/28 14:12
*/
public class BookController2 {
private IBookService bookService;
// 查所有
public Result getAll() {
return new Result(true, bookService.list());
}
// 根据id查询
public Result getById( { Integer id)
return new Result(true, bookService.getById(id));
}
// 分页查询
public Result getByPage( Integer currentPage,
{ Integer pageSize)
IPage page = new Page(currentPage, pageSize);
bookService.page(page);
return new Result(true, page.getRecords());
}
public Result save( { Book book)
// Result result = new Result();
// boolean flag = bookService.save(book);
// result.setFlag(flag);
// return result;
return new Result(bookService.save(book));
}
public Result delete( { Integer id)
return new Result(bookService.removeById(id));
}
public Result update( { Book book)
return new Result(bookService.updateById(book));
}
}让所有方法的返回结果都是
Result
类型。
★前后端数据协议
- 设计统一的返回值结果类型便于前端开发读取数据。
- 返回值结果类型可以根据需求自行设定,没有固定格式。
- “返回值结果模型类” 用于后端与前端进行数据格式统一,也称为前后端数据协议。
1.5.6 表现层Web开发
在前后端分离结构设计中,页面归属前端服务器。
在单体工程中,页面放置在
resources
目录下的static
目录中。前端开发部分就不写笔记了,对应视频为
P43-P49