前言
Spring 的优点
Spring 是 Java企业版(Java Enterprise Edition,JEE,也称J2EE)的轻量级代替品。无需开发重量级的Enterprise JavaBean(EJB),Spring 为企业级 Java 开发提供了一种相对简单的方法,通过依赖注入和面向切面编程,用简单的 Java 对象(Plain Old Java Object,POJO)实现了 EJB 的功能。
Spring 的缺点
虽然 Spring 的组件代码是轻量级的,但它的配置却是重量级的。一开始,Spring 用 XML 配置,而且是很多 XML 配置。Spring 2.5 引入了基于注解的组件扫描,这消除了大量针对应用程序自身组件的显式 XML 配置。Spring 3.0 引入了基于Java 的配置,这是一种类型安全的可重构配置方式,可以代替 XML。
所有这些配置都代表了开发时的损耗。因为在思考 Spring 特性配置和解决业务问题之间需要进行思维切换,所以编写配置挤占了编写应用程序逻辑的时间。和所有框架一样,Spring 实用,但与此同时它要求的回报也不少。
除此之外,项目的依赖管理也是一件耗时耗力的事情。在环境搭建时,需要分析要导入哪些库的坐标,而且还需要分析导入与之有依赖关系的其他库的坐标,一旦选错了依赖的版本,随之而来的不兼容问题就会严重阻碍项目的开发进度。
使用 SpringBoot 解决上面的问题
SpringBoot 对上述 Spring 的缺点进行的改善和优化,基于约定优于配置的思想,可以让开发人员不必在配置与逻辑业务之间进行思维的切换,全身心的投入到逻辑业务的代码编写中,从而大大提高了开发的效率,一定程度上缩短了项目周期。
概述
SpringBoot 是由 Pivotal 团队提供的全新框架,其设计目的是用来简化新 Spring应用的初始搭建以及开发过程。该框架使用了特定的方式来进行配置,从而使开发人员不再需要定义样板化的配置。通过这种方式,SpringBoot 致力于在蓬勃发展的快速应用开发领域(rapid application development)成为领导者。
SpringBoot 官方网址:https://spring.io/projects/spring-boot#overview
SpringBoot 开发版本推荐
- Springboot 目前分为两大版本系列,1.x 系列和 2.x 系列
- 如果是使用 Eclipse,推荐安装 Spring Tool Suite (STS) 插件
- 如果使用 IDEA 旗舰版,自带了 SpringBoot 插件,使用很方便
- 必须使用 Maven 3.3+,Maven 目前最新版本为3.8.1(2021-05-03)
- 推荐使用 Java 8,Java11,Java16,SpringBoot 1.x 系列的版本兼容Java 6,SpringBoot 2.x 系列需要至少 Java8
SpringBoot 的特性
- 能够快速创建基于 Spring 的应用程序,避免了大量的配置文件
- 能够直接使用 java main 方法启动内嵌的 Tomcat 服务器运行 SpringBoot 程序,不需要部署 war 包文件
- 提供约定的 starter POM 来简化 Maven 配置,让 Maven 的配置变得简单
- 自动化配置,根据项目的 Maven 依赖配置,Springboot 自动配置 Spring、Spring MVC 等
- 提供了一些大型项目中常见的非功能性特性,如嵌入式服务器、安全、指标,健康检测、外部配置等
- 基本可以完全不使用 XML 配置文件,采用注解配置
- SpringBoot 不是对 Spring 功能上的增强,而是提供了一种快速使用 Spring 的方式,简单理解,就是框架的框架
SpringBoot 四大核心
-
自动配置【重点】 针对很多 Spring 应用程序和常见的应用功能,SpringBoot 能自动提供相关配置。可以根据简单的配置甚至0配置来搭建整个项目。
Spring Boot 的自动配置是一个运行时(更准确地说,是应用程序启动时)的过程,考虑了众多因素,才决定 Spring 配置应该用哪个,不该用哪个。该过程是 Spring 自动完成的。
-
起步依赖【重点】 起步依赖本质上是一个Maven项目对象模型(Project Object Model,POM),定义了对其他库的传递依赖,这些东西加在一起即支持某项功能。
告诉 SpringBoot 需要什么功能,它就能引入需要的依赖库。通过起步依赖机制(Starter),简化 jar 包的引用,解决 jar 版本冲突问题。
-
Actuator【了解】 是 SpringBoot 的程序监控器,可监控 Spring 应用程序上下文中的 Bean、查看自动配置决策、Controller 映射、线程活动、应用程序健康状况等,能够深入运行中的 Spring Boot 应用程序,一探 Spring boot 程序的内部信息。 -
命令行界面【了解】 这是 SpringBoot 的可选特性,主要针对 Groovy 语言使用; Groovy 是一种基于JVM(Java虚拟机) 的敏捷开发语言,它结合了 Python、Ruby 和 Smalltalk的许多强大的特性,Groovy 代码能够与 Java 代码很好地结合,也能用于扩展现有代码,由于其运行在 JVM 上的特性,Groovy 可以使用其他 Java 语言编写的库。
SpringBoot 重要策略
SpringBoot 框架中还有两个非常重要的策略:开箱即用和约定优于配置。
- 开箱即用,Outofbox,是指在开发过程中,通过在 MAVEN 项目的 pom 文件中添加相关依赖包,然后使用对应注解来代替繁琐的 XML 配置文件以管理对象的生命周期。这个特点使得开发人员摆脱了复杂的配置工作以及依赖的管理工作,更加专注于业务逻辑。
- 约定优于配置,Convention over configuration,是一种由 SpringBoot 本身来配置目标结构,由开发者在结构中添加信息的软件设计范式。这一特点虽降低了部分灵活性,增加了BUG定位的复杂性,但减少了开发人员需要做出决定的数量,同时减少了大量的XML配置,并且可以将代码编译、测试和打包等工作自动化。
SpringBoot 应用系统开发模板的基本架构设计从前端到后台进行说明:前端常使用模板引擎,主要有 FreeMarker 和 Thymeleaf,它们都是用 Java 语言编写的,渲染模板并输出相应文本,使得界面的设计与应用的逻辑分离,同时前端开发还会使用到 Bootstrap、AngularJS、JQuery 等;在浏览器的数据传输格式上采用 Json,非 xml,同时提供 RESTful API;SpringMVC 框架用于数据到达服务器后处理请求;到数据访问层主要有Hibernate、MyBatis、JPA 等持久层框架;数据库常用 MySQL;开发工具推荐 IntelliJIDEA。
SpringBoot 入门
【一般不用】网站创建地址:https://start.spring.io/
项目创建
1、点击创建项目
2、选择 Spring Initializr 快捷创建 SpringBoot 项目(需要联网),点击下一步
3、输入对应的公司名和骨架名,选择对应的JDK版本以及编辑包名,点击下一步
4、添加所需的依赖,这里选择Spring Web,点击下一步
5、选择项目名和项目本地存储的位置
6、项目创建完成
项目结构
结构说明
名称 | 描述 |
---|
java | java 代码 | com.fc | 包名,所有的Java代码都需要放在此包下 | SpringbootProjectApplication【重点】 | SpringBoot 启动类,程序的入口 | resources【重点】 | 资源 | static【重点】 | 存放静态资源,如图片、 存放静态资源,如图片、 存放静态资源,如图片、 存放静态资源,如图片、 CSS、JavaScript等,可以直接访问 | templates【重点】 | 存放 Web页面的模板文件,只能通过Controller进行访问,类似WEB-INF | application.properties【重点】 | 等同于application.yml文件,用于存放程序的各种依赖模块配置信息,比如服务端口,数据库连接配置等 | pom.xml【重点】 | maven 配置文件 | .mvn|mvnw|mvnw.cmd【了解】 | 使用脚本操作执行 maven相关命令,国内使用较少可删 除 | .gitignore | 使用版本控制工具 ,设置一些忽略提交内容 |
pom.xml
<?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 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>2.4.2</version>
<relativePath/>
</parent>
<groupId>com.fc</groupId>
<artifactId>springboot-01</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>06_SpringBoot-01</name>
<description>Demo project for Spring Boot</description>
<properties>
<java.version>1.8</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>
项目启动
控制台无报错说明启动成功
案例代码
Controller
@RestController
@RequestMapping("user")
public class UserController {
@RequestMapping("findAll")
public String findAll() {
return "findAll";
}
}
【注意】新创建的类一定要位于 Application 启动类同级目录或者下,否则 SpringBoot 加载不到。
启动类
@SpringBootApplication
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
Spring Boot 核心配置文件
两个核心配置格式【重点】
SpringBoot是基于约定的,所以很多配置都有默认值,但如果想使用自己的配置替换默认配置的话,就可以使用 application.properties 或者application.yml(application.yaml)进行配置,SpringBoot 默认会从Resources 目录下加载 application.properties 或application.yml(application.yaml)文件。
properties 文件格式
application.properties 文件是键值对类型的文件(默认)
application.properties 配置文件
# 配置Tomcat的端口号
server.port=8081
# 配置Web访问的路径前缀
server.servlet.context-path=/properties
yml 文件格式
概述
SpringBoot 还可以使用 yml 文件进行配置,YML 文件格式是 YAML (YAML Ain’t Markup Language)编写的文件格式,YAML 是一种直观的能够被电脑识别的的数据数据序列化格式,并且容易被人类阅读,容易和脚本语言交互的,可以被支持 YAML 库的不同的编程语言程序导入,比如: C/C++, Ruby, Python, Java, Perl, C#, PHP等。YML 文件是以数据为核心的,比传统的xml方式更加简洁,YML文件的扩展名可以使用.yml或者.yaml。
语法要求
- key: value; kv之间有空格
- 大小写敏感
- 使用缩进表示层级关系
- 缩进不允许使用tab,只允许空格
- 缩进的空格数不重要,只要相同层级的元素左对齐即可
- '#'表示注释
- “与”"表示字符串内容会被转义/不转义
案例代码
application.yml 配置文件
server:
port: 8082
servlet:
context-path: /yml
数据类型
配置文件
user:
name: "易烊千玺"
age: 21
gender: true
birthday: 2000/1/1 12:30:20
hobby: ["唱", "跳", "rap"]
food:
- 烤羊排
- 烤韭菜
- 烤鱿鱼
score: {"Java": 100, "MySQL": 100}
car:
name: 比亚迪
实体类
@Data
public class Car {
private String name;
}
@Component
@ConfigurationProperties(prefix = "user")
@Data
public class User {
private String name;
private Integer age;
private Boolean gender;
private Date birthday;
private String[] hobby;
private List<String> food;
private Map<String, Object> score;
private Car car;
}
【注意】如果是字符串类型的数据,单引号下转义字符无效,双引号下转义字符才能生效
【补充】配置处理器
解决 ConfigurationProperties 注解报错以及在配置文件中使用提示
在 ConfigInfo类中使用了 类中使用了 ConfigurationProperties 注解后, IDEA 会出现一个警告, 不影响程序的执行
Spring Boot Configuration Annotation Processor not found in classpath
点击 open documentnation 跳转到网页,在网页中提示需要加一个依赖,将这个依赖拷贝,粘贴到 pom.xml 文件中即可解决,此时 application.yml 配置文件中的黄色警告线也会消失,并且配置文件中也能使用提示了
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
<optional>true</optional>
</dependency>
另外,SpringBoot 建议在打包的时候不声明此配置处理器,因为这是和我们的业务无关的内容,我们可以在插件配置中添加如下代码来实现,并且在 2.4.2 版本添加上了此功能的优化,并不需要我们再去手动配置了。
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<excludes>
<exclude>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
</exclude>
</excludes>
</configuration>
</plugin>
properties 和 yaml 的加载顺序
如果 application.properties 文件与 application.yml 配置文件同时存在,当application.properties 和 application.yaml 进行优先级加载时,它们都会加载,并不是application.properties 加载了 application.yaml 就不加载了,而是它们的内容根据优先级的高低进行合并(merge)并以 application.properties 为主。
常用配置
官方描述:https://docs.spring.io/spring-boot/docs/2.4.5/reference/htmlsingle/#common-application-properties
配置 | 默认值 | 描述 |
---|
spring.aop.auto | true | 添加@EnableAspectJAutoProxy。 | spring.aop.proxy-target-class | true | 与标准的基于Java接口的代理(false)相反,是否要创建基于子类的代理(CGLIB)(true)。 | spring.application.name | | 应用名称。 | spring.autoconfigure.exclude | | 要排除的自动配置类。 | spring.config.import | | 导入其他配置数据。 | spring.config.location | | 替换默认设置的配置文件位置。 | spring.config.name | application | 配置文件名。 | spring.jackson.date-format | | 日期格式字符串或标准日期格式类名称。例如,yyyy-MM-dd HH:mm:ss 。 | spring.jackson.time-zone | | 格式化日期时使用的时区。例如,“ America / Los_Angeles”或“ GMT + 10”。 |
服务器相关
| | |
---|
server.port | 8080 | 服务器HTTP端口。 | server.servlet.context-path | | | server.servlet.path | | | server.address | | 服务器应绑定到的网络地址。 | server.server-header | | 用于服务器响应标头的值(如果为空,则不发送标头)。 | server.servlet.application-display-name | application | 显示应用程序的名称。 | server.servlet.context-parameters.* | | Servlet上下文初始化参数。 | server.servlet.context-path | | 应用程序的上下文路径。 | server.servlet.encoding.charset | | 编码集 |
SpringMVC 相关
配置 | 默认值 | 描述 |
---|
spring.mvc.view.prefix | | Spring MVC视图前缀。 | spring.mvc.view.suffix | | Spring MVC视图后缀。 | spring.mvc.format.date | | 要使用的日期格式,例如dd / MM / yyyy 。 | spring.mvc.format.time | | 使用的时间格式,例如“ HH:mm:ss”。 | spring.mvc.format.date-time | | 要使用的日期时间格式,例如“ yyyy-MM-dd HH:mm:ss”。 | spring.mvc.static-path-pattern | /** | 用于静态资源的访问路径加上前缀,默认无前缀。 | spring.mvc.servlet.load-on-startup | -1 | 加载调度程序Servlet的启动优先级。 | spring.mvc.servlet.path | / | 调度程序Servlet的路径。为此属性设置自定义值与PathPatternParser匹配策略不兼容。 | **spring.web.resources.static-locations: ** | classpath:/** | 用于静态资源的本地路径加上前缀,默认无前缀。 |
Datasource 相关
配置 | 默认值 | 描述 |
---|
spring.datasource.driver-class-name | | 数据库的连接 | spring.datasource.password | | 数据库的登录密码。 | spring.datasource.username | | 数据库的登录用户名。 | spring.datasource.url | | 数据库的JDBC URL。 | spring.datasource.type | HikariDataSource | 要使用的连接池实现的完全限定名称。默认情况下,它是从类路径中自动检测到的,使用的是HikariCP,可以修改为Druid。 |
MyBatis 相关
属性配置 | 默认值 | 描述 |
---|
mybatis.config-location | | mybatis-config.xml 配置文件的本地路径 | mybatis.mapper-locations | | mapper.xml 映射文件的本地路径 | mybatis.type-aliases-package | | 扫描指定包下的类作为别名 | mybatis.configuration.cache-enabled | true | 二级缓存 | mybatis.configuration.log-impl | | 日志输出 | mybatis.configuration.map-underscore-to-camel-case | false | 开启驼峰命名自动映射 | mybatis.configuration.lazy-loading-enabled | false | 开启延迟加载的全局开关 | mybatis.configuration.aggressive-lazy-loading | false | 开启时,任一方法的调用都会加载该对象的所有延迟加载属性。否则,每个延迟加载属性会按需加载 | mybatis.configuration.use-generated-keys | false | 允许 JDBC 支持自动生成主键,需要数据库驱动支持。如果设置为true,将强制使用自动生成主键。 | mybatis.configuration.default-statement-timeout | | 超时时间,它决定数据库驱动等待数据库响应的秒数 |
Quartz 定时任务相关
Elasticsearch 相关
配置 | 默认值 | 描述 |
---|
spring.elasticsearch.jest.password | | | spring.elasticsearch.jest.proxy.host | | | spring.elasticsearch.jest.proxy.port | | | spring.elasticsearch.jest.read-timeout | | | spring.elasticsearch.jest.username | | |
PageHelper 相关
| | |
---|
pagehelper.dialect | | 自动选择对应的数据库方言 | pagehelper.reasonable | false | 分页合理化 | pagehelper.support-methods-arguments | false | 支持通过 Mapper 接口参数来传递分页参数 |
自定义配置
在 SpringBoot 的核心配置文件中,除了使用内置的配置项之外,我们还可以在自定义配置,然后采用对应的注解去读取配置的属性值
@Value
Value 注解用于获取配置文件中属性键对应的值并赋值给声明的变量
使用格式
@Value("${属性名}")
1、编写 application.yml 配置文件
server:
port: 8080
user:
username: 易烊千玺
password: 123456
2、声明 Controller 并通过 @Value 注解使用自定义配置
@RestController
@RequestMapping("user")
public class UserController {
@Value("${user.username}")
private String username;
@Value("${password}")
private String password;
@RequestMapping("customConfiguration")
public String customConfiguration() {
return "用户名:" + username + " 密码:" + password;
}
}
@ConfigurationProperties
ConfigurationProperties 注解用于将整个文件映射成一个对象,用于自定义配置项比较多的情况
格式
@ConfigurationProperties(prefix = "属性名")
1、编写 application.yml 配置文件
server:
port: 8080
student:
username: 易烊千玺
password: 123456
age: 20
info: 送你一朵小红花
2、声明配置类
@Component
@ConfigurationProperties(prefix = "student")
public class ConfigInfo {
private String username;
private String password;
private int age;
private String info;
}
【注意】
1、必须将类注册到容器中,否则会报错!可以使用 @Component (类上)或者 @EnableConfigurationProperties (配置类上)
1、@ConfigurationProperties 注解必须声明 prefix 属性
2、成员变量必须要和配置文件中的属性相同
3、一定要在配置的对象中加上 set、get 方法
3、声明 Controller
@RestController
@RequestMapping("student")
public class StudentController {
@Autowired
private ConfigInfo configInfo;
@RequestMapping("getConfigInfo")
public String getConfigInfo() {
return configInfo.getUsername() + configInfo.getPassword() + configInfo.getAge() + configInfo.getInfo();
}
}
SpringBoot 常用注解
@Configuration【重点】
被@Configuration 修饰的类作为一个配置类,相当于 xml 配置文件,会在启动时被加载。通常和 @Bean 标签配合使用,相当于 xml 配置文件中的 Bean 标签。
概述
-
指示一个类声明了一个或多个 @Bean 方法,并且可以由 Spring 容器进行处理,以在运行时为这些 bean 生成 bean 定义和服务请求。 -
元注解为 @Component,可以使用 @Autowired 进行依赖注入。 -
@Configuration 类不仅可以使用组件扫描来引导,还可以自己使用 @ComponentScan 注解来配置组件扫描。 -
@Configuration 默认会生成当前类的代理对象,可以通过内部的 proxyBeanMethods 属性设置为 false 来生成真实对象。用来达到跳过 Spring 容器并强制执行 @Bean 注解生成对象的生命周期的目的
案例代码
1、TestConfig
@Configuration
public class TestConfig {
public TestConfig() {
System.out.println("相当于Spring中的xml配置文件");
}
public void testComponent() {
System.out.println("测试@Component");
}
}
2、控制层
@Controller
@RequestMapping("test")
public class ConfigController {
@Autowired
public TestConfig testConfig;
@RequestMapping("component")
public void testComponent() {
testConfig.testComponent();
}
}
@Bean【重点】
概述
指示方法产生一个由Spring容器管理的bean。该注解的 name 属性的名称和语义有意类似于 Spring XML 配置文件中的 bean 标签,并且默认是单例的,如果想要修改为多例,可以使用 @Scope 注解进行声明。
bean 的 name 属性默认使用对象的首字母小写的形式,也可以自定义,支持一个字符串数组,允许给一个 bean 对象起多个别名。
案例代码
1、User 实体类
public class User {
private int id;
private String name;
private int age;
private String info;
}
2、TestConfig
@Configuration
public class TestConfig {
@Bean
public User getUser() {
return new User(1, "易烊千玺", 20, "送你一朵小红花");
}
}
3、控制层
@Controller
@RequestMapping("test")
public class ConfigController {
@Autowired
public User user;
@RequestMapping("bean")
public void testBean() {
System.out.println(user);
}
}
@PostConstruct【重点】
常用此注解来完成一些初始化的操作
概述
被 @PostConstruct 修饰的方法会在服务器加载的时候运行,并且只会被服务器执行一次。PostConstruct 在构造方法以及@Autowired之后执行。
案例代码
@Component
public class TestInit {
@PostConstruct
public void init() {
System.out.println("@PostConstruct注解,启动时加载");
}
}
@Import【了解】
概述
表明给容器导入一个组件,4.2之前只能是配置类 ,4.2之后也可以是普通的类,相当于交给 Spring 容器中创建一个当前类的对象,对象名为完整的全限定名
案例代码
1、实体类
@Data
public class Cat {
private String name;
}
2、配置类
@Import({Cat.class})
@Configuration()
public class TestConfig {
}
3、启动测试类
@SpringBootApplication
public class Application {
public static void main(String[] args) {
ConfigurableApplicationContext run = SpringApplication.run(Application.class, args);
Cat cat1 = run.getBean("com.fc.bean.Cat", Cat.class);
Cat cat2 = run.getBean(Cat.class);
System.out.println(cat1);
System.out.println(cat2);
}
}
@Conditional【了解】
概述
条件装配:指示仅当所有指定条件都匹配时,组件才有资格注册。
@Conditional 注解的子注解
案例代码
实体类
@Data
public class Son {
}
@Data
public class Wife {
}
@Data
public class GirlFriend {
}
配置类
@Configuration
public class BeanConfig {
public Wife getWife() {
return new Wife();
}
@ConditionalOnBean(Wife.class)
@Bean(name = "son")
public Son getSon() {
return new Son();
}
@ConditionalOnMissingBean(Wife.class)
@Bean("girlFriend")
public GirlFriend getGirlFriend() {
return new GirlFriend();
}
}
【注意】被作为条件的类一定要在被引用之前注册到 Spring 容器中,否则根据条件注册会失败
启动类
@SpringBootApplication
public class Application {
public static void main(String[] args) {
ConfigurableApplicationContext run = SpringApplication.run(Application.class, args);
boolean hasSon = run.containsBean("son");
if (hasSon) {
Son son = run.getBean("son", Son.class);
System.out.println("有儿子:" + son);
} else {
System.out.println("没有儿子");
}
boolean hasGirlFriend = run.containsBean("girlFriend");
if (hasGirlFriend) {
GirlFriend girlFriend = run.getBean(GirlFriend.class);
System.out.println("有女朋友:" + girlFriend);
} else {
System.out.println("没有女朋友");
}
}
}
其他常用注解【了解】
注解 | 描述 |
---|
@SpringBootApplication | 放置在Springboot启动类上,表明该类是开启Springboot容器的入口。2.0中的注解@SpringBootApplication是注解@SpringBootConfiguration、@EnableAutoConfiguration和@ComponentScan的组合 | @SpringBootConfiguration | 它表示的是该类会作为Springboot的一个配置类 | @EnableAutoConfiguration | 它表示开启自动配置功能。包含@AutoConfigurationPackage以及@Import两个注解 | @AutoConfigurationPackage | 表示自动注入包 | @ImportResource | 用来加载 xml 配置文件,常用于导入 xml 中装配好的组件(classpath:xxx.xml) | @ComponentScan | 用来将指定包(如果未指定就是将当前类所在包及其子孙包)加入SpringIOC的包扫描,本质上等于context:component-scan配置 | @Inject | 等价于默认的@Autowired,只是没有required属性 | @Qualifier | 当有多个同一类型的Bean时,可以用@Qualifier(“name”)来指定。与@Autowired配合使用。@Qualifier限定描述符除了能根据名字进行注入,但能进行更细粒度的控制如何选择候选者 | @Resource(name=”name”,type=”type”) | 没有括号内内容的话,默认byName。与@Autowired干类似的事,相当于@Autowired加上@Qualifier。此注解不是Spring的注解,而是Java Web中的注解 |
SpringBoot 静态资源访问
概述
SpingBoot 会默认访问/static (or /public or /resources or /META-INF/resources 下所有的静态资源,访问方式是当前项目名加资源名即可。
访问方式: 当前项目根路径/静态资源名
可以给访问路径以及本地路径添加指定前缀,用来实现 SpringMvc.mxl 配置文件中 resources 标签的映射功能
配置访问路径前缀
spring.mvc.static-path-pattern=/img/**
访问路径为:当前项目根路径/img/静态资源名
配置本地路径前缀
spring.web.resources.static-locations=classpath:/static/img/
访问路径为:当前项目根路径 / + 静态资源名
使用 WebJars 下的静态资源【了解】
pom.xml 文件
<dependency>
<groupId>org.webjars</groupId>
<artifactId>jquery</artifactId>
<version>3.6.0</version>
</dependency>
static 下的 html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<script src="webjars/jquery/3.6.0/jquery.min.js"></script>
<body>
</body>
</html>
能够正常访问到静态资源
欢迎页面【了解】
静态资源路径下的 index.html 为欢迎页面,启动项目会默认访问此页面
图标【了解】
将 favicon.ico 文件放在静态资源路径下即可,如果访问不到图标,可以重新编译项目并重启浏览器
SpringBoot 整合 JSP【了解】
1、pom.xml 文件添加依赖并指定JSP文件的编译目录
<?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 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>2.4.2</version>
<relativePath/>
</parent>
<groupId>com.fc</groupId>
<artifactId>springboot-06-jsp</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>springboot-06-jsp</name>
<description>Demo project for Spring Boot</description>
<properties>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.apache.tomcat.embed</groupId>
<artifactId>tomcat-embed-jasper</artifactId>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
</dependency>
<dependency>
<groupId>javax.servlet.jsp</groupId>
<artifactId>javax.servlet.jsp-api</artifactId>
<version>2.3.1</version>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>jstl</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>
<resources>
<resource>
<directory>src/main/webapp</directory>
<targetPath>META-INF/resources</targetPath>
<includes>
<include>**/*.*</include>
</includes>
</resource>
</resources>
</build>
</project>
2、application.yml 配置文件中配置试图解析
server:
port: 8080
spring:
mvc:
view:
prefix: /
suffix: .jsp
3、声明 Controller
@Controller
@RequestMapping("test")
public class JspController {
@RequestMapping("jsp")
public String getJsp(Model model) {
model.addAttribute("username", "易烊千玺");
return "index";
}
}
4、创建 index.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" isELIgnored="false" %>
<html>
<head>
<title>测试JSP</title>
</head>
<body>
${username}
</body>
</html>
SpringBoot 整合 MyBatis【重点】
使用 Druid 连接池访问数据库
1、pom.xml 配置文件引入依赖
<?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 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>2.4.2</version>
<relativePath/>
</parent>
<groupId>com.fc</groupId>
<artifactId>springboot-07-mybatis</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>springboot-07-mybatis</name>
<description>Demo project for Spring Boot</description>
<properties>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>2.1.2</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.48</version>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid-spring-boot-starter</artifactId>
<version>1.1.21</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>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
2、application.yml 配置文件配置数据源以及 MyBatis 相关配置
server:
port: 8080
spring:
datasource:
type: com.alibaba.druid.pool.DruidDataSource
driver-class-name: com.mysql.jdbc.Driver
url: jdbc:mysql://localhost:3306/FC2021?useSSL=false&characterEncoding=UTF-8&serverTimezone=Asia/Shanghai
username: root
password: root
mybatis:
type-aliases-package: com.fc.bean
mapper-locations: classpath:mapper/*.xml
configuration:
log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
cache-enabled: true
3、创建实体类
@Component
@Data
public class Student implements Serializable {
private Integer id;
private String name;
private Integer age;
private String gender;
private Date birthday;
private String info;
}
【注意】因为使用了二级缓存,所以需要实现序列化
3、创建 Dao 层接口
@Repository
public interface StudentDao {
List<Student> findAll();
}
这里也可以使用 @Mapper 注解,相当于启动类中的 @MapperScan
4、创建 Mapper 映射文件
<?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" >
<mapper namespace="com.fc.dao.StudentDao">
<cache/>
<select id="findAll" resultType="com.fc.bean.Student">
select * from student
</select>
</mapper>
【注意】映射文件需要放在 src\main\resources\mapper 路径下
5、创建 Service 层接口
public interface StudentService {
List<Student> findAll();
}
6、创建 Service 层接口实现类
@Service("studentService")
public class StudentServiceImpl implements StudentService {
@Autowired
private StudentDao studentDao;
@Override
public List<Student> findAll() {
return studentDao.findAll();
}
}
7、创建 Controller
@RestController
@RequestMapping("student")
public class StudentController {
@Autowired
private StudentService studentService;
@RequestMapping("findAll")
public List<Student> findAll() {
return studentService.findAll();
}
}
8、修改启动类,添加扫描接口的注解
@MapperScan("com.fc.dao")
@SpringBootApplication
public class Springboot07MybatisApplication {
public static void main(String[] args) {
SpringApplication.run(Springboot07MybatisApplication.class, args);
}
}
使用分页插件
1、pom.xml 文件中添加依赖
<dependency>
<groupId>com.github.pagehelper</groupId>
<artifactId>pagehelper-spring-boot-starter</artifactId>
<version>1.2.13</version>
</dependency>
2、Controller 中添加方法
@RestController
@RequestMapping("student")
public class StudentController {
@Autowired
private StudentService studentService;
@RequestMapping("findAllByPage")
public PageInfo<Student> findAllByPage(Integer pageNum, Integer pageSize) {
PageHelper.startPage(pageNum, pageSize);
List<Student> list = studentService.findAll();
return new PageInfo<>(list);
}
}
开启事务支持
service 实现类中添加事务注解
@Service("studentService")
public class StudentServiceImpl implements StudentService {
@Autowired
private StudentDao studentDao;
@Transactional(isolation = Isolation.READ_COMMITTED,
readOnly = true,
propagation = Propagation.REQUIRED)
@Override
public List<Student> findAll() {
return studentDao.findAll();
}
}
修改启动类,添加开启事务支持的注解,但是没必要,会自动开启
@EnableTransactionManagement
@MapperScan("com.fc.dao")
@SpringBootApplication
public class Springboot07MybatisApplication {
public static void main(String[] args) {
SpringApplication.run(Springboot07MybatisApplication.class, args);
}
}
SpringBoot 实现 RESTful
概述
REST(英文:Representational State Transfer,简称 REST)
一种互联网软件架构设计的风格,但它并不是标准,它只是提出了一组客户端和服务器 交互时的架构理念和设计原则,基于这种理念和原则设计的接口可以更简洁,更有层次,REST 这个词,是 Roy Thomas Fielding 在他 2000 年的博士论文中提出的。任何的技术都可以实现这种理念,如果一个架构符合 REST 原则,就称它为 RESTFul 架构
比如我们要访问一个 http 接口:http://localhost:8080/boot/order?id=1021&status=1
采用 RESTful 风格则访问的地址为 http://localhost:8080/boot/order/1021/1
我们通常使用 @PathVariable 注解获取 url 中的数据。
案例代码
1、pom.xml 配置文件引入依赖
<?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 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>2.4.2</version>
<relativePath/>
</parent>
<groupId>com.fc</groupId>
<artifactId>springboot-08-restful</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>springboot-08-restful</name>
<description>Demo project for Spring Boot</description>
<properties>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>2.1.2</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.48</version>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid-spring-boot-starter</artifactId>
<version>1.1.21</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</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>
<configuration>
<excludes>
<exclude>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</exclude>
</excludes>
</configuration>
</plugin>
</plugins>
</build>
</project>
2、application.yml 配置文件配置数据源以及 MyBatis 相关配置
server:
port: 8080
spring:
datasource:
driver-class-name: com.mysql.jdbc.Driver
url: jdbc:mysql://localhost:3306/FC2021?useSSL=false&characterEncoding=UTF-8&serverTimezone=Asia/Shanghai
username: root
password: root
mybatis:
type-aliases-package: com.fc.bean
configuration:
cache-enabled: true
log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
mapper-locations: classpath:mapper/*.xml
3、创建实体类
@Component
@Data
public class Student implements Serializable {
private Integer id;
private String name;
private Integer age;
private String gender;
private Date birthday;
private String info;
}
3、创建 Dao 层接口
@Repository
public interface StudentDao {
List<Student> findAll();
int add(Student student);
int update(Student student);
int delete(Integer id);
}
4、创建 Mapper 映射文件
<?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" >
<mapper namespace="com.fc.dao.StudentDao">
<cache/>
<select id="findAll" resultType="com.fc.bean.Student">
select * from student
</select>
<insert id="add" parameterType="com.fc.bean.Student">
insert into student(name, age, gender, birthday, info) value (#{name}, #{age}, #{gender}, #{birthday}, #{info})
</insert>
<update id="update" parameterType="com.fc.bean.Student">
update student set name = #{name}, gender = #{gender}, age = #{age}, info = #{info} where id = #{id}
</update>
<delete id="delete" parameterType="Integer">
delete from student where id = #{id}
</delete>
</mapper>
5、创建 Service 层接口
public interface StudentService {
List<Student> findAll();
int add(Student student);
int update(Student student);
int delete(Integer id);
}
6、创建 Service 层接口实现类
@Service("studentService")
public class StudentServiceImpl implements StudentService {
@Autowired
private StudentDao studentDao;
@Transactional(isolation = Isolation.READ_COMMITTED,
readOnly = true,
propagation = Propagation.REQUIRED)
@Override
public List<Student> findAll() {
return studentDao.findAll();
}
@Transactional(readOnly = false)
@Override
public int add(Student student) {
return studentDao.add(student);
}
@Transactional(readOnly = false)
@Override
public int update(Student student) {
return studentDao.update(student);
}
@Transactional(readOnly = false)
@Override
public int delete(Integer id) {
return studentDao.delete(id);
}
}
7、创建 Controller
@RestController
@RequestMapping("student")
public class StudentController {
@Autowired
private StudentService studentService;
@GetMapping()
public List<Student> findAll() {
return studentService.findAll();
}
@PostMapping("{name}/{age}/{gender}/{birthday}/{info}")
public Map<String, Object> add(@PathVariable("name") String name,
@PathVariable("age") Integer age,
@PathVariable("gender") String gender,
@PathVariable("birthday") String birthday,
@PathVariable("info") String info) {
Map<String, Object> map = new HashMap<>();
SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
Date date = null;
try {
date = simpleDateFormat.parse(birthday);
Student student = new Student();
student.setName(name);
student.setAge(age);
student.setGender(gender);
student.setBirthday(date);
student.setInfo(info);
int affectedRows = studentService.add(student);
if (affectedRows > 0) {
map.put("code", 200);
map.put("message", "添加成功");
} else {
map.put("code", 500);
map.put("message", "添加失败");
}
} catch (ParseException e) {
e.printStackTrace();
}
return map;
}
@PutMapping("{id}/{name}/{age}/{gender}/{birthday}/{info}")
public Map<String, Object> update(@PathVariable("id") Integer id,
@PathVariable("name") String name,
@PathVariable("age") Integer age,
@PathVariable("gender") String gender,
@PathVariable("birthday") String birthday,
@PathVariable("info") String info) {
Map<String, Object> map = new HashMap<>();
SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
Date date = null;
try {
date = simpleDateFormat.parse(birthday);
Student student = new Student();
student.setId(id);
student.setName(name);
student.setAge(age);
student.setGender(gender);
student.setBirthday(date);
student.setInfo(info);
int affectedRows = studentService.update(student);
if (affectedRows > 0) {
map.put("code", 200);
map.put("message", "修改成功");
} else {
map.put("code", 500);
map.put("message", "修改失败");
}
} catch (ParseException e) {
e.printStackTrace();
}
return map;
}
@DeleteMapping("{id}")
public Map<String, Object> delete(@PathVariable("id") Integer id) {
Map<String, Object> map = new HashMap<>();
int affectedRows = studentService.delete(id);
if (affectedRows > 0) {
map.put("code", 200);
map.put("message", "删除成功");
} else {
map.put("code", 500);
map.put("message", "删除失败");
}
return map;
}
}
8、修改启动类,添加扫描接口的注解
@MapperScan("com.fc.dao")
@SpringBootApplication
public class Springboot08RestfulApplication {
public static void main(String[] args) {
SpringApplication.run(Springboot08RestfulApplication.class, args);
}
}
9、使用 Postman 访问各接口
# POST
http://localhost:8080/student/易烊千玺/20/男/2021-02-09 10:21:13/真帅
# DELETE
http://localhost:8080/student/13
# PUT
http://localhost:8080/student/13/迪丽热巴/20/女/2021-02-09 18:49:13/年轻
# GET
http://localhost:8080/student
RESTful 风格的特点
- 传递参数变简单了 传递参数变简单了
- 服务提供者对外只了一个接口,而不是传统的 服务提供者对外只了一个接口,而不是传统的 服务提供者对外只了一个接口,而不是传统的 服务提供者对外只了一个接口,而不是传统的 服务提供者对外只了一个接口,而不是传统的 服务提供者对外只了一个接口,而不是传统的 服务提供者对外只了一个接口,而不是传统的 CRUD四个接口
- 一定要注意两个请求路径会发生请求路径冲突问题。如果出现了冲突,要么修改请求路径,要么修改请求方式
RESTful 原则【了解】
1、增使用 post 请求、删使用 delete 请求、改使用 put 请求、查使用 get 请求
2、请求路径不要出现动词
? 例如:查询订单接口
/boot/order/1021/1(推荐)
/boot/queryOrder/1021/1(不推荐)
3、分页、排序等操作,不需要使用斜杠传参数分页、排序等操作,不需要使用 RESTful 风格传参
? 例如:订单列表接口
/boot/orders?page=1&sort=desc(推荐)
一般传的参数不是数据库表字段,可以不采用 RESTful 风格传参
SpringBoot 异常处理
概述
SpringBoot 默认的已经提供了一套处理异常的机制。 一旦程序中出现了异常 SpringBoot 会向 /error 的 url 发送请求。在 SpringBoot 中提供了一个 叫 BasicExceptionController 来处理 /error 请求,然后跳转到默认显示异常的页面来展示异常信息。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-5YWzDG4P-1662614879129)(Pictures/异常.png)]
常用注解
注解 | 描述 | 核心属性及作用 |
---|
@ControllerAdvice | 对所有异常集中处理,对Controller层进行拦截 | value,用于指定异常拦截的包名 | @RestControllerAdvice | 相当于@ControllerAdvice加上@ResponseBody注解 | value,用于指定异常拦截的包名 | @ExceptionHandler | 对指定异常进行处理 | value,异常的Class对象 |
案例代码
1、创建自定义异常
public class MyException extends Exception {
public MyException() {
super();
}
public MyException(String message) {
super(message);
}
}
2、创建异常处理器
@RestControllerAdvice
public class CustomExceptionHandler {
@ExceptionHandler(value = Exception.class)
public Map<String, Object> handlerSystemException(Exception e, HttpServletRequest request) {
Map<String, Object> map = new HashMap<>();
map.put("msg", e.getMessage());
map.put("url", request.getRequestURL());
return map;
}
@ExceptionHandler(value = MyException.class)
public Map<String, Object> handlerMyException(MyException e, HttpServletRequest request) {
Map<String, Object> map = new HashMap<>();
map.put("msg", e.getMessage());
map.put("url", request.getRequestURL());
return map;
}
}
3、创建 Controller
@RestController
@RequestMapping("exception")
public class ExceptionController {
@RequestMapping("systemException")
public void testSystemException() {
int i = 1 / 0;
}
@RequestMapping("customException")
public void testCustomException() throws MyException {
throw new MyException("自定义异常");
}
}
SpringBoot 过滤器
1、创建自定义过滤器
@WebFilter("/*")
public class MyFilter implements Filter {
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
System.out.println("自定义过滤器被执行");
filterChain.doFilter(servletRequest, servletResponse);
}
}
2、创建 Controller
@RestController
@RequestMapping("filter")
public class FilterController {
@RequestMapping("test")
public String testFilter() {
return "filter";
}
}
3、修改启动类,添加 @ServletComponentScan 注解,此注解用于@WebServlet、@WebFilter、@WebListener注解自动注册
@SpringBootApplication
@ServletComponentScan
public class Springboot10FilterApplication {
public static void main(String[] args) {
SpringApplication.run(Springboot10FilterApplication.class, args);
}
}
SpringBoot 拦截器
1、创建自定义拦截器
public class MyInterceptor implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
System.out.println("preHandle");
return true;
}
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
System.out.println("postHandle");
}
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
System.out.println("afterCompletion");
}
}
2、创建拦截器配置类,这里的操作就相当于 SpringMVC 的注册拦截器 ,@Configuration就相当于一个 springMvc.xml
@Configuration
public class InterceptorConfig implements WebMvcConfigurer {
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(new MyInterceptor()).addPathPatterns("/interceptor/*");
WebMvcConfigurer.super.addInterceptors(registry);
}
}
3、在 static 目录下创建 index.html 页面
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>测试主页</title>
</head>
<body>
主页
</body>
</html>
4、创建 Controller
@Controller
@RequestMapping("interceptor")
public class InterceptorController {
@RequestMapping("test")
public String test() {
return "/index.html";
}
}
SpringBoot 整合 JUnit4
概述
Spring Test 与 JUnit 等其他测试框架结合起来,提供了便捷高效的测试手段。而 Spring Boot Test 是在 Spring Test 之上的再次封装,增加了切片测试,增强了mock 能力。
SpringBootTest 注解
@SpringBootTest 替代了 Spring-Test 中的 @ContextConfiguration 注解,目的是加载 ApplicationContext,启动 Spring 容器。
使用 @SpringBootTest 时并没有像 @ContextConfiguration 一样显示指定 locations 或 classes 属性,原因在于 @SpringBootTest 注解会自动检索程序的配置文件,检索顺序是从当前包开始,逐级向上查找被@SpringBootApplication 或 @SpringBootConfiguration 注解的类。
案例代码
1、pom.xml 导入对应的依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
2、声明 Controller
@Controller
public class UserController {
public void test() {
System.out.println("测试");
}
}
3、编写测试类
@RunWith(SpringRunner.class)
@SpringBootTest
class ApplicationTests {
@Autowired
private UserController userController;
@Test
void contextLoads() {
userController.test();
}
}
SpringBoot 整合 JUnit5
概述
Spring Boot 2.2.0 版本开始引入 JUnit 5 作为单元测试默认库
作为最新版本的 JUnit 框架,JUnit5 与之前版本的 Junit 框架有很大的不同。由三个不同子项目的几个不同模块组成。
JUnit 5 = JUnit Platform + JUnit Jupiter + JUnit Vintage
JUnit Platform: Junit Platform 是在 JVM 上启动测试框架的基础,不仅支持 Junit 自制的测试引擎,其他测试引擎也都可以接入。
JUnit Jupiter: JUnit Jupiter 提供了JUnit5的新的编程模型,是JUnit5新特性的核心。内部包含了一个测试引擎,用于在 Junit Platform 上运行。
JUnit Vintage: 由于 JUint 已经发展多年,为了照顾老的项目,JUnit Vintage 提供了兼容 JUnit4.x,Junit3.x 的测试引擎。
注意:
1、SpringBoot 2.4 以上版本移除了默认对 Vintage 的依赖。如果需要兼容 junit4 需要自行引入(不能使用junit4的功能 @Test)
2、Junit 类具有 Spring 的功能,比如 @Autowired 能够自动注入容器中的对象、比如 @Transactional 声明的测试方法,测试完成后能够自动回滚
常用注解
注解 | 描述 |
---|
@Test | 表示方法是测试方法。但是与JUnit4的@Test不同,他的职责非常单一不能声明任何属性,拓展的测试将会由Jupiter提供额外测试 | @ParameterizedTest | 表示方法是参数化测试 | @RepeatedTest | 表示方法是重复测试的测试模板 | @DisplayName | 声明测试类或测试方法的自定义显示名称 | @BeforeEach | 表示在每个单元测试之前执行,类似于JUnit 4的@Before | @AfterEach | 表示在每个单元测试之后执行,类似于 JUnit 4的@After | @BeforeAll | 表示在所有单元测试之前执行,类似于JUnit 4的@BeforeClass | @AfterAll | 表示在所有单元测试之后执行,类似于JUnit 4的@AfterClass | @Tag | 表示单元测试类别,类似于JUnit4中的@Categories | @Disabled | 表示测试类或测试方法不执行,类似于JUnit4中的@Ignore | @Timeout | 表示测试方法运行如果超过了指定时间将会返回错误 | @RepeatedTest | 表示测试方法会被重复测试 | @ExtendWith | 为测试类或测试方法提供扩展类引用,类似于JUnit4中的@RunWith |
案例代码
@SpringBootTest
@DisplayName("测试DisplayName注解加到类上")
class ApplicationTests {
@Autowired
private User user;
@Test
void testDI() {
System.out.println("测试从容器里获取的对象:" + user);
}
@Test
void contextLoads() {
System.out.println("测试Junit5中的@Test方法");
}
@DisplayName("测试DisplayName注解加到方法上")
@Test
void testDisplayName() {
System.out.println("测试DisplayName注解");
}
@Disabled
@Test
@Tag("测试注解")
void testDisabled() {
System.out.println("测试Disabled注解:被此注解声明的测试方法将不会生效");
}
@Timeout(value = 3, unit = TimeUnit.SECONDS)
@Test
void testTimeout() {
try {
Thread.sleep(5000);
System.out.println("测试Timeout注解,超时报错");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
@RepeatedTest(3)
void testRepeatedTest() {
System.out.println("测试RepeatedTest注解:重复测试,可以手动指定测试的次数");
}
@BeforeEach()
void testBeforeEach() {
System.out.println("测试BeforeEach注解:任意测试方法执行前执行此方法");
}
@AfterEach
void testAfterEach() {
System.out.println("测试AfterEach注解:任意测试方法执行后执行此方法");
}
@BeforeAll
static void testBeforeAll() {
System.out.println("测试BeforeAll注解:所有测试方法执行前执行此方法(一次)");
}
@AfterAll
static void testAfterAll() {
System.out.println("测试AfterAll注解:所有测试方法执行后执行此方法(一次)");
}
}
SpringBoot 多环境配置
application-profile
为每个环境创建一配置文件,命名必须以 application-环境标识 .properties | yml
1、创建 application-dev.yml 配置文件
server:
port: 8080
servlet: context-path: /dev
2、创建 application-product.yml 配置文件
server:
port: 8081
servlet:
context-path: /product
3、创建 application-test.yml 配置文件
server:
port: 8082
servlet:
context-path: /test
通过配置文件指定
在 application.yml 总配置文件中添加对应的使用环境
spring:
profiles:
active: product
通过命令行携带参数指定
java -jar xxx.jar --spring.profiles.active=dev
【注意】优先级最高
@Profile 条件装配
@Profile 注解
指示当一个或多个指定的配置文件处于活动状态时,该组件才有资格注册。此注解可用于类或者方法上,配合 @Component 或者 @Bean 创建对象到容器中。
案例代码
声明三个配置文件
person:
name: 马尔扎哈
age: 200
1、创建 application-dev.yml 配置文件
person:
name: 易烊千玺
age: 21
2、创建 application-test.yml 配置文件
person:
name: 迪丽热巴
age: 22
3、创建 application-product.yml 配置文件
person:
name: 马尔扎哈
age: 200
4、声明一个接口以及三个实现类
public interface Person {
}
@Profile("product")
@ConfigurationProperties("person")
@Data
@Component
public class GrandPa implements Person {
private String name;
private Integer age;
}
@Profile("dev")
@ConfigurationProperties("person")
@Data
@Component
public class Father implements Person {
private String name;
private Integer age;
}
@Profile("test")
@ConfigurationProperties("person")
@Data
@Component
public class Son implements Person {
private String name;
private Integer age;
}
声明控制层中的方法
@RestController
@RequestMapping("user")
public class UserController {
@Autowired
private Person person;
@RequestMapping("getPerson")
public Person getPerson() {
return person;
}
}
通过 application.yml 文件指定运行的环境
spring:
profiles:
active: product
此时我们从 Spring 容器中获取到的 Person 对象响应到浏览器上就是 { “name”: “马尔扎哈”,“age”: 200}
【补充】SpringBoot 字符编码集
如果出现了字符编码集的问题,在 application.yml 文件中添加以下内容即可
server:
servlet:
encoding:
enabled: true
force: true
charset: UTF-8
【补充】SpringBoot 热部署
为了方便开发,可以在创建项目时手动勾选热部署,或导入该依赖,就不需要每次重启配置类
实现原理主要是因为它使用了两种不同的类加载器。基础类加载器用于加载不会改变的类(比如第三方库中的类),重启类加载器用于加载你应用程序中的类。当应用程序启动时,重启类加载器中的类将会被替换掉,这就意味着重启将比冷启动更快!
1、pom.xml 配置文件添加依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<optional>true</optional>
</dependency>
2、点击 Settings
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-opH1D1Ey-1662614879133)(Pictures/SpringBoot热部署01.png)]
3、勾选自动构建项目
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-2UZ7otqw-1662614879133)(Pictures/SpringBoot热部署02.png)]
4、Ctrl + Alt + Shift + / 打开保持页面,并选择 Registry
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-FcwQpvPi-1662614879134)(Pictures/SpringBoot热部署03.png)]
5、在注册页面找到 complier.automake.allow.when.app.running 并勾选 Close
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-NkZVwoxs-1662614879135)(Pictures/SpringBoot热部署04.png)]
【补充】关闭启动时的 SpringBoot Logo
修改启动类
@SpringBootApplication
public class SpringbootApplication {
public static void main(String[] args) {
SpringApplication springApplication = new SpringApplication(SpringbootApplication.class);
springApplication.setBannerMode(Banner.Mode.OFF);
springApplication.run(args);
}
}
【补充】替换启动时的 SpringBoot Logo
在 src/main/resources 目录下添加 banner.txt 文件,此文件中的内容就是 Logo。可以利用网站生成图标: https://www.bootschool.net/ascii 或者 http://patorjk.com/software/taag/,将生成好的图标文字粘贴到 ,将生成好的图标文字粘贴到 banner.txt 文件中即可。
或者直接使用图片,在配置文件中进行对应的配置也可以
spring.banner.image.location=classpath:
@Profile(“dev”) @ConfigurationProperties(“person”) @Data @Component public class Father implements Person { private String name; private Integer age; }
@Profile(“test”) @ConfigurationProperties(“person”) @Data @Component public class Son implements Person { private String name; private Integer age; }
声明控制层中的方法
```java
@RestController
@RequestMapping("user")
public class UserController {
// 注入一个接口
@Autowired
private Person person;
@RequestMapping("getPerson")
public Person getPerson() {
return person;
}
}
通过 application.yml 文件指定运行的环境
spring:
profiles:
active: product
此时我们从 Spring 容器中获取到的 Person 对象响应到浏览器上就是 { “name”: “马尔扎哈”,“age”: 200}
【补充】SpringBoot 字符编码集
如果出现了字符编码集的问题,在 application.yml 文件中添加以下内容即可
server:
servlet:
encoding:
enabled: true
force: true
charset: UTF-8
【补充】SpringBoot 热部署
为了方便开发,可以在创建项目时手动勾选热部署,或导入该依赖,就不需要每次重启配置类
实现原理主要是因为它使用了两种不同的类加载器。基础类加载器用于加载不会改变的类(比如第三方库中的类),重启类加载器用于加载你应用程序中的类。当应用程序启动时,重启类加载器中的类将会被替换掉,这就意味着重启将比冷启动更快!
1、pom.xml 配置文件添加依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<optional>true</optional>
</dependency>
2、点击 Settings
[外链图片转存中…(img-opH1D1Ey-1662614879133)]
3、勾选自动构建项目
[外链图片转存中…(img-2UZ7otqw-1662614879133)]
4、Ctrl + Alt + Shift + / 打开保持页面,并选择 Registry
[外链图片转存中…(img-FcwQpvPi-1662614879134)]
5、在注册页面找到 complier.automake.allow.when.app.running 并勾选 Close
[外链图片转存中…(img-NkZVwoxs-1662614879135)]
【补充】关闭启动时的 SpringBoot Logo
修改启动类
@SpringBootApplication
public class SpringbootApplication {
public static void main(String[] args) {
SpringApplication springApplication = new SpringApplication(SpringbootApplication.class);
springApplication.setBannerMode(Banner.Mode.OFF);
springApplication.run(args);
}
}
【补充】替换启动时的 SpringBoot Logo
在 src/main/resources 目录下添加 banner.txt 文件,此文件中的内容就是 Logo。可以利用网站生成图标: https://www.bootschool.net/ascii 或者 http://patorjk.com/software/taag/,将生成好的图标文字粘贴到 ,将生成好的图标文字粘贴到 banner.txt 文件中即可。
或者直接使用图片,在配置文件中进行对应的配置也可以
spring.banner.image.location=classpath:
|