1.简介
SpringBoot是一个javaweb的开发框架,和SpringMVC类似,对比其他javaweb框架的好处,官方说是简化开发,约定大于配置, you can "just run",能迅速的开发web应用,几行代码开发一个http接口。
官网:https://spring.io/projects/spring-boot
1.1 特点
SpringBoot所具备的特征有:
(1)可以创建独立的Spring应用程序,并且基于其Maven或Gradle插件,可以创建可执行的JARs和WARs;
(2)内嵌式容器简化Web项目,内嵌Tomcat或Jetty等Servlet容器;
(3)开箱即用,提供各种默认配置来简化项目配置,提供自动配置的“starter”项目对象模型(POMS)以简化Maven配置;
(4)尽可能自动配置Spring容器;
(5)提供准备好的特性,如指标、健康检查和外部化配置;
(6)绝对没有代码生成,不需要XML配置, 没有冗余代码生成和XML配置的要求。
1.2 准备工作
-
java version "1.8.0_181"
-
Maven-3.6.1
-
SpringBoot 3.x 最新版
开发工具:
-
IDEA
1.3 总结
简单来说就是SpringBoot其实不是什么新的框架,它默认配置了很多框架的使用方式,就像maven整合了所有的jar包,spring boot整合了所有的框架 。
2.HelloWorld
2.1 官网生成项目
使用Spring Initializr 的 Web页面创建项目
1、打开 https://start.spring.io/
2、填写项目信息
3、点击”Generate Project“按钮生成项目;下载此项目
4、解压项目包,并用IDEA以Maven项目导入,一路下一步即可,直到项目导入完毕。
5、如果是第一次使用,可能速度会比较慢,包比较多、需要耐心等待一切就绪。
2.2 在idea中创建项目
1、创建一个新项目
2、选择spring initalizr , 可以看到默认就是去官网的快速构建工具那里实现
3、填写项目信息
4、选择初始化的组件(初学勾选 Web 即可)
5、填写项目路径
6、等待项目构建成功
2.3 遇到的问题
1. 生产的java类图标是
解决办法:
2.maven以及生产类爆红
解决办法:
1.在项目中删除.mvn文件
2.在设置中找到build,找到maven,设置自己的maven版本
2.4 测试
1、在主程序的同级目录下,新建一个controller包,一定要在同级目录下,否则识别不到
2、在包中新建一个HelloController类
@RestController
public class HelloController {
@RequestMapping("/hello")
public String hello() {
return "Hello World";
}
}
3、编写完毕后,从主程序启动项目,浏览器发起请求,看页面返回;控制台输出了 Tomcat 访问的端口号!
简单几步,就完成了一个web接口的开发,SpringBoot就是这么简单。所以我们常用它来建立我们的微服务项目!
3.springboot运行原理剖析
3.1 @springBooApplicationt结论:
-
SpringBoot在启动的时候从类路径下的META-INF/spring.factories中获取EnableAutoConfiguration指定的值
-
将这些值作为自动配置类导入容器 , 自动配置类就生效 , 帮我们进行自动配置工作;
-
整个J2EE的整体解决方案和自动配置都在springboot-autoconfigure的jar包中;
-
它会给容器中导入非常多的自动配置类 (xxxAutoConfiguration), 就是给容器中导入这个场景需要的所有组件 , 并配置好这些组件 ;
-
有了自动配置类 , 免去了我们手动编写配置注入功能组件等的工作;
3.2 springApplication类结论
1、推断应用的类型是普通的项目还是Web项目
2、查找并加载所有可用初始化器 , 设置到initializers属性中
3、找出所有的应用程序监听器,设置到listeners属性中
4、推断并设置main方法的定义类,找到运行的主类
4. yaml配置
SpringBoot使用一个全局的配置文件 , 配置文件名称是固定的
-
application.properties
-
语法结构 :key=value
-
-
application.yml
-
语法结构 :key:空格 value
-
配置文件的作用 :修改SpringBoot自动配置的默认值,因为SpringBoot在底层都给我们自动配置好了;
例如,修改启动的端口号
server.prort=8081
4.1 yaml概述
YAML是 "YAML Ain't a Markup Language" (YAML不是一种标记语言)的递归缩写。在开发的这种语言时,YAML 的意思其实是:"Yet Another Markup Language"(仍是一种标记语言)
以前的配置文件,大多数都是使用xml来配置;比如一个简单的端口配置,我们来对比下yaml和xml
传统xml配置:
<server>
<port>8081<port>
</server>
yaml配置:
形式 key:空格+value
server:
prot: 8080
4.2 基本语法
说明:语法要求严格!
1、空格不能省略
2、以缩进来控制层级关系,只要是左边对齐的一列数据都是同一个层级的。
3、属性和值的大小写都是十分敏感的。
字面量:普通的值 [ 数字,布尔值,字符串 ]
字面量直接写在后面就可以 , 字符串默认不用加上双引号或者单引号;
k: v
注意:
-
“ ” 双引号,不会转义字符串里面的特殊字符 , 特殊字符会作为本身想表示的意思;
比如 :name: "kuang \n shen" 输出 :kuang 换行 shen
-
'' 单引号,会转义特殊字符 , 特殊字符最终会变成和普通字符一样输出
比如 :name: ‘kuang \n shen’ 输出 :kuang \n shen
对象、Map(键值对)
#对象、Map格式
k:
v1:
v2:
在下一行来写对象的属性和值得关系,注意缩进;比如:
student:
name: qinjiang
age: 3
行内写法
student: {name: qinjiang,age: 3}
数组( List、set )
用 - 值表示数组中的一个元素,比如:
pets:
- cat
- dog
- pig
行内写法
pets: [cat,dog,pig]
修改SpringBoot的默认端口号
配置文件中添加,端口号的参数,就可以切换端口;
server:
port: 8082
4.3 注入配置文件
4.3.1 原始方式注入
通过@Value()注解方式注入
package com.heima.pojo;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
@Component
public class Dog {
@Value("黑麻")
private String name;
@Value("18")
private Integer age;
public Dog() {
}
public Dog(String name, Integer age) {
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
@Override
public String toString() {
return "Dog{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
}
测试输出:
package com.heima;
import com.heima.pojo.Dog;
import com.heima.pojo.Person;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
@SpringBootTest
class Springboot02ConfigApplicationTests {
@Autowired
private Dog dog;
@Test
void contextLoads() {
System.out.println(dog);
}
}
4.3.2 yaml方式注入
1.创建一个复杂的实体类Person
package com.heima.pojo;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.PropertySource;
import org.springframework.stereotype.Component;
import java.util.Date;
import java.util.List;
import java.util.Map;
@Component
public class Person {
private String name;
private Integer age;
private Boolean happy;
private Date birth;
private Map<String,Object> maps;
private List<Object> list;
private Dog dog;
//有参构造,无参构造,get,set,toString()
}
2.创建一个yaml配置文件application.yaml
person:
name: heima
age: 18
happy: false
birth: 2003/6/1
maps: {k1: v1,k2: v2}
list:
- code
- music
- girl
dog:
name: 旺财
age: 3
3.在实体类Person中加入注解@ConfigurationProperties(prefix = "person")注入yaml配置
package com.heima.pojo;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.PropertySource;
import org.springframework.stereotype.Component;
import java.util.Date;
import java.util.List;
import java.util.Map;
/*
@ConfigurationProperties作用:
将配置文件中配置的每一个属性的值,映射到这个组件中;
告诉SpringBoot将本类中的所有属性和配置文件中相关的配置进行绑定
参数 prefix = “person” : 将配置文件中的person下面的所有属性一一对应
*/
@Component //注册bean
@ConfigurationProperties(prefix = "person")
public class Person {
private String name;
private Integer age;
private Boolean happy;
private Date birth;
private Map<String,Object> maps;
private List<Object> lists;
private Dog dog;
}
4.IDEA 提示,springboot配置注解处理器没有找到,让我们看文档,我们可以查看文档,找到一个依赖!
<!-- 导入配置文件处理器,配置文件进行绑定就会有提示,需要重启 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
<optional>true</optional>
</dependency>
5.测试
package com.heima;
import com.heima.pojo.Dog;
import com.heima.pojo.Person;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
@SpringBootTest
class Springboot02ConfigApplicationTests {
@Autowired
private Person person;
@Test
void contextLoads() {
System.out.println(person);
}
}
6.得到输出
Person{name='heima', age=18, happy=false, birth=Sun Jun 01 00:00:00 CST 2003, maps={k1=v1, k2=v2}, list=[code, music, girl], dog=Dog{name='旺财', age=3}}
4.4 加载指定配置文件
@PropertySource :加载指定的配置文件;
@configurationProperties:默认从全局配置文件中获取值;
1、我们去在resources目录下新建一个person.properties文件
name=heima
2、然后在我们的代码中指定加载person.properties文件
@PropertySource(value = "classpath:person.properties")
@Component //注册bean
public class Person {
@Value("${name}")
private String name; ......
}
3、再次输出测试一下:指定配置文件绑定成功!
4.5 配置文件占位符
配置文件还可以编写占位符生成随机数
person:
name: qinjiang${random.uuid} # 随机uuid
age: ${random.int} # 随机int
happy: false
birth: 2000/01/01
maps: {k1: v1,k2: v2}
lists:
- code
- girl
- music
dog:
name: ${person.hello:other}_旺财
age: 1
4.6 yaml和properties对比
1、@ConfigurationProperties只需要写一次即可 , @Value则需要每个字段都添加
2、松散绑定:这个什么意思呢? 比如我的yml中写的last-name,这个和lastName是一样的, - 后面跟着的字母默认是大写的。这就是松散绑定。
3、JSR303数据校验 , 这个就是我们可以在字段是增加一层过滤器验证 , 可以保证数据的合法性.
4、复杂类型封装,yml中可以封装对象 , 使用value就不支持
4.7 结论
配置yml和配置properties都可以获取到值 , 强烈推荐 yml;
如果我们在某个业务中,只需要获取配置文件中的某个值,可以使用一下 @value;
如果说,我们专门编写了一个JavaBean来和配置文件进行一一映射,就直接@configurationProperties,不要犹豫!
5.JSR303数据校验
Springboot中可以用@validated来校验数据,如果数据异常则会统一抛出异常,方便异常中心统一处理。我们这里来写个注解让我们的name只能支持Email格式;
@Component //注册bean
@ConfigurationProperties(prefix = "person")
@Validated //数据校验
public class Person {
@Email(message="邮箱格式错误") //name必须是邮箱格式
private String name;
}
运行结果 :default message [不是一个合法的电子邮件地址];
使用数据校验,可以保证数据的正确性;
常见参数
@NotNull(message="名字不能为空")
private String userName;
@Max(value=120,message="年龄最大不能查过120")
private int age;
@Email(message="邮箱格式错误")
private String email;
空检查 @Null 验证对象是否为null
@NotNull 验证对象是否不为null, 无法查检长度为0的字符串 @NotBlank 检查约束字符串是不是Null还有被Trim的长度是否大于0,只对字符串,且会去掉前后空格 @NotEmpty 检查约束元素是否为NULL或者是EMPTY. Booelan检查 @AssertTrue 验证 Boolean 对象是否为 true @AssertFalse 验证 Boolean 对象是否为 false 长度检查 @Size(min=, max=) 验证对象(Array,Collection,Map,String)长度是否在给定的范围之内 @Length(min=, max=) string is between min and max included.日期检查 @Past 验证 Date 和 Calendar 对象是否在当前时间之前 @Future 验证 Date 和 Calendar 对象是否在当前时间之后 @Pattern 验证 String 对象是否符合正则表达式的规则 等等除此以外,我们还可以自定义一些数据校验规则
6.多环境配置
profile是Spring对不同环境提供不同配置功能的支持,可以通过激活不同的环境版本,实现快速切换环境;
6.1 多配置文件
我们在主配置文件编写的时候,文件名可以是 application-{profile}.properties/yml , 用来指定多个环境版本;
例如:
application-test.properties 代表测试环境配置
application-dev.properties 代表开发环境配置
但是Springboot并不会直接启动这些配置文件,它默认使用application.properties主配置文件;
我们需要通过一个配置来选择需要激活的环境:
#比如在配置文件中指定使用dev环境,我们可以通过设置不同的端口号进行测试;
#我们启动SpringBoot,就可以看到已经切换到dev下的配置了;
spring.profiles.active=dev
6.2 yaml的多文档块
和properties配置文件中一样,但是使用yml去实现不需要创建多个配置文件,更加方便了 !
但如今,yaml中spring.profiles.active方法以及过时了,所以不推荐使用了...
server:
port: 8081
#选择要激活那个环境块
spring:
profiles:
active: prod
---
server:
port: 8083
spring:
profiles: dev #配置环境的名称
---
server:
port: 8084
spring:
profiles: prod #配置环境的名称
注意:如果yml和properties同时都配置了端口,并且没有激活其他环境 , 默认会使用properties配置文件的!
6.3 配置文件加载位置
外部加载配置文件的方式十分多,我们选择最常用的即可,在开发的资源文件中进行配置!
官方外部配置文件说明参考文档
springboot 启动会扫描以下位置的application.properties或者application.yml文件作为Spring boot的默认配置文件:
优先级1:项目路径下的config文件夹配置文件
优先级2:项目路径下配置文件
优先级3:资源路径下的config文件夹配置文件
优先级4:资源路径下配置文件
优先级由高到底,高优先级的配置会覆盖低优先级的配置;
SpringBoot会从这四个位置全部加载主配置文件;互补配置;
我们在最低级的配置文件中设置一个项目访问路径的配置来测试互补问题;
#配置项目的访问路径
server.servlet.context-path=/heima
6.4 拓展,运维小技巧
指定位置加载配置文件
我们还可以通过spring.config.location来改变默认的配置文件位置
项目打包好以后,我们可以使用命令行参数的形式,启动项目的时候来指定配置文件的新位置;这种情况,一般是后期运维做的多,相同配置,外部指定的配置文件优先级最高
java -jar spring-boot-config.jar --spring.config.location=F:/application.properties
7.自动配置原理
我们知道springboot中,有大量的配置信息,我们无法将它们全部记住,因此,我们有什么巧妙的办法,在我们需要时使用它们。
7.1 自动装配
我们以HttpEncodingAutoConfiguration(Http编码自动配置)为例解释自动配置原理
//表示这是一个配置类,和以前编写的配置文件一样,也可以给容器中添加组件;
@Configuration
//启动指定类的ConfigurationProperties功能;
//进入这个HttpProperties查看,将配置文件中对应的值和HttpProperties绑定起来;
//并把HttpProperties加入到ioc容器中
@EnableConfigurationProperties({HttpProperties.class})
//Spring底层@Conditional注解
//根据不同的条件判断,如果满足指定的条件,整个配置类里面的配置就会生效;
//这里的意思就是判断当前应用是否是web应用,如果是,当前配置类生效
@ConditionalOnWebApplication(
type = Type.SERVLET
)
//判断当前项目有没有这个类CharacterEncodingFilter;SpringMVC中进行乱码解决的过滤器;
@ConditionalOnClass({CharacterEncodingFilter.class})
//判断配置文件中是否存在某个配置:spring.http.encoding.enabled;
//如果不存在,判断也是成立的
//即使我们配置文件中不配置pring.http.encoding.enabled=true,也是默认生效的;
@ConditionalOnProperty(
prefix = "spring.http.encoding",
value = {"enabled"},
matchIfMissing = true
)
public class HttpEncodingAutoConfiguration {
//他已经和SpringBoot的配置文件映射了
private final Encoding properties;
//只有一个有参构造器的情况下,参数的值就会从容器中拿
public HttpEncodingAutoConfiguration(HttpProperties properties) {
this.properties = properties.getEncoding();
}
//给容器中添加一个组件,这个组件的某些值需要从properties中获取
@Bean
@ConditionalOnMissingBean //判断容器没有这个组件?
public CharacterEncodingFilter characterEncodingFilter() {
CharacterEncodingFilter filter = new OrderedCharacterEncodingFilter();
filter.setEncoding(this.properties.getCharset().name());
filter.setForceRequestEncoding(this.properties.shouldForce(org.springframework.boot.autoconfigure.http.HttpProperties.Encoding.Type.REQUEST));
filter.setForceResponseEncoding(this.properties.shouldForce(org.springframework.boot.autoconfigure.http.HttpProperties.Encoding.Type.RESPONSE));
return filter;
}
//。。。。。。。
}
7.2 总结
-
一但这个配置类生效;这个配置类就会给容器中添加各种组件;
-
这些组件的属性是从对应的XXXproperties类中获取的,这些类里面的每一个属性又是和配置文件绑定的;
-
所有在配置文件中能配置的属性都是在XXXProperties类中封装着,也就是,如果我们想要修改默认的配置信息,根据XXXProperties中的属性值在properties文件中进行修改即可。
-
配置文件能配置什么就可以参照某个功能对应的这个属性
//从配置文件中获取指定的值和bean的属性进行绑定
@ConfigurationProperties(prefix = "spring.http")
public class HttpProperties {
// .....
}
7.3 精髓
1、SpringBoot启动会加载大量的自动配置类
2、我们看我们需要的功能有没有在SpringBoot默认写好的自动配置类当中;
3、我们再来看这个自动配置类中到底配置了哪些组件;(只要我们要用的组件存在在其中,我们就不需要再手动配置了)
4、给容器中自动配置类添加组件的时候,会从properties类中获取某些属性。我们只需要在配置文件中指定这些属性的值即可;
xxxxAutoConfigurartion:自动配置类;给容器中添加组件
xxxxProperties:封装配置文件中相关属性;
7.4 @Condition派生注解
我们怎么能知道有哪些配置是springboot在启动时自动装配的呢;
在properties文件中使用如下语句即可查找到我们需要的信息
debug=true
我们可以看到
Positive matches(自动配置类启用的:正匹配)
Positive matches:
-----------------
下的都是启动springboot后,自动帮我们装配的配置类;
Negative matches:(没有启动,没有匹配成功的自动配置类:负匹配)
Negative matches:
-----------------
这即是我们需要一定条件才能装配的配置类 ,
Unconditional classes: (没有条件的类)
Unconditional classes:
-----------------
是不需要条件的配置类,但仍需手动配置
8 Web开发探究
核心:理解自动装配原理
使用SpringBoot的步骤:
1、创建一个SpringBoot应用,选择我们需要的模块,SpringBoot就会默认将我们的需要的模块自动配置好
2、手动在配置文件中配置部分配置项目就可以运行起来了
3、专注编写业务代码,不需要考虑以前那样一大堆的配置了。
要熟悉掌握开发,之前学习的自动配置的原理一定要搞明白!
比如SpringBoot到底帮我们配置了什么?我们能不能修改?我们能修改哪些配置?我们能不能扩展?
-
向容器中自动配置组件 :*** Autoconfiguration
-
自动配置类,封装配置文件的内容:***Properties
9.静态资源处理
在原先的ssm项目中,我们的前端页面资源等等都是写在webapp下的,但在springboot中,没有这个webapp给我们存放我们需要的静态资源,因此,springboot有它的方式为我们存放静态资源,但是SpringBoot对于静态资源放置的位置,是有规定的!
9.1 静态资源映射规则
SpringBoot中,SpringMVC的web配置都在 WebMvcAutoConfiguration 这个配置类里面;
我们可以去看看 WebMvcAutoConfigurationAdapter 中有很多配置方法;
有一个方法:addResourceHandlers 添加资源处理
@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
if (!this.resourceProperties.isAddMappings()) {
// 已禁用默认资源处理
logger.debug("Default resource handling disabled");
return;
}
// 缓存控制
Duration cachePeriod = this.resourceProperties.getCache().getPeriod();
CacheControl cacheControl = this.resourceProperties.getCache().getCachecontrol().toHttpCacheControl();
// webjars 配置
if (!registry.hasMappingForPattern("/webjars/**")) {
customizeResourceHandlerRegistration(registry.addResourceHandler("/webjars/**")
.addResourceLocations("classpath:/META-INF/resources/webjars/")
.setCachePeriod(getSeconds(cachePeriod)).setCacheControl(cacheControl));
}
// 静态资源配置
String staticPathPattern = this.mvcProperties.getStaticPathPattern();
if (!registry.hasMappingForPattern(staticPathPattern)) {
customizeResourceHandlerRegistration(registry.addResourceHandler(staticPathPattern)
.addResourceLocations(getResourceLocations(this.resourceProperties.getStaticLocations()))
.setCachePeriod(getSeconds(cachePeriod)).setCacheControl(cacheControl));
}
}
读一下源代码:比如所有的 /webjars/** , 都需要去 classpath:/META-INF/resources/webjars/ 找对应的资源;
9.2 webjars
Webjars本质就是以jar包的方式引入我们的静态资源 , 我们以前要导入一个静态资源文件,直接导入即可。
使用SpringBoot需要使用Webjars,我们可以去搜索一下:
要使用jQuery,我们只要要引入jQuery对应版本的pom依赖即可!
<dependency> <groupId>org.webjars</groupId> <artifactId>jquery</artifactId> <version>3.7.1</version> </dependency>
导入完毕,查看webjars目录结构,访问jquery.js文件
访问:只要是静态资源,SpringBoot就会去对应的路径寻找资源,我们这里访问:http://localhost:8080/webjars/jquery/3.7.1/jquery.js
9.3 第二种静态资源映射规则
那我们项目中要是使用自己的静态资源该怎么导入呢?我们看下一行代码;
我们去找staticPathPattern发现第二种映射规则 :/** , 访问当前的项目任意资源,它会去找 resourceProperties 这个类,我们可以点进去看一下分析:
// 进入方法
public String[] getStaticLocations() {
return this.staticLocations;
}
// 找到对应的值
private String[] staticLocations = CLASSPATH_RESOURCE_LOCATIONS;
// 找到路径
private static final String[] CLASSPATH_RESOURCE_LOCATIONS = {
"classpath:/META-INF/resources/",
"classpath:/resources/",
"classpath:/static/",
"classpath:/public/"
};
ResourceProperties 可以设置和我们静态资源有关的参数;这里面指向了它会去寻找资源的文件夹,即上面数组的内容。
所以得出结论,以下四个目录存放的静态资源可以被我们识别:
"classpath:/META-INF/resources/"
"classpath:/resources/"
"classpath:/static/"
"classpath:/public/"
我们可以在resources根目录下新建对应的文件夹,都可以存放我们的静态文件;
比如我们访问 http://localhost:8080/1.js , 他就会去这些文件夹中寻找对应的静态资源文件;
9.4 自定义静态资源路径
我们也可以自己通过配置文件来指定一下,哪些文件夹是需要我们放静态资源文件的,在application.properties中配置;
spring.resources.static-locations=classpath:/coding/,classpath:/heima/
一旦自己定义了静态文件夹的路径,原来的自动配置就都会失效了!
首页处理,静态资源文件夹说完后,我们继续向下看源码!可以看到一个欢迎页的映射,就是我们的首页!因为这个方法现在弃用了,就不做过多赘述了...
10. Thymeleaf模板引擎
10.1 模板引擎
- Thymeleaf
- freemarker
- jsp
- ...
前端交给我们的页面,是html页面。以前开发,我们需要把他们转成jsp页面,jsp的好处就是当我们查出一些数据转发到JSP页面以后,我们可以用jsp轻松实现数据的显示,及交互等。
jsp支持非常强大的功能,包括能写Java代码,但是现在springboot是以jar包的形式,而不是war,并且我们用的还是嵌入式的Tomcat,所以呢,它现在默认是不支持jsp的。
那不支持jsp,如果我们直接用纯静态页面的方式,那给我们开发会带来非常大的麻烦,所以我们可以使用模板引擎来实现交互。
10.2 Thymeleaf
10.2.1 引入thymeleaf
在springboot中就是引入一个starter依赖即可
Thymeleaf 官网:https://www.thymeleaf.org/
Thymeleaf 在Github 的主页:https://github.com/thymeleaf/thymeleaf
Spring官方文档:找到对应的版本
https://docs.spring.io/spring-boot/docs/2.2.5.RELEASE/reference/htmlsingle/#using-boot-starter
找到对应的pom依赖,导入maven依赖即可
<!-- thymeleaf模板引擎 --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-thymeleaf</artifactId> </dependency>
10.2.2 thymeleaf分析
我们首先按照SpringBoot的自动配置原理看一下我们这个Thymeleaf的自动配置规则,在按照那个规则,我们进行使用。
我们可以找到Thymeleaf的自动配置类:ThymeleafProperties
@ConfigurationProperties(
prefix = "spring.thymeleaf"
)
public class ThymeleafProperties {
private static final Charset DEFAULT_ENCODING;
public static final String DEFAULT_PREFIX = "classpath:/templates/";
public static final String DEFAULT_SUFFIX = ".html";
private boolean checkTemplate = true;
private boolean checkTemplateLocation = true;
private String prefix = "classpath:/templates/";
private String suffix = ".html";
private String mode = "HTML";
private Charset encoding;
}
我们可以在其中看到默认的前缀和后缀!
我们只需要把我们的html页面放在类路径下的templates下,thymeleaf就可以帮我们自动渲染了。
使用thymeleaf什么都不需要配置,只需要将他放在指定的文件夹下即可!
10.2.3 测试
1、编写一个TestController
package com.heima.controller;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@Controller
public class TestController {
@RequestMapping("/test")
public String test(){
return "test";
}
}
2、编写一个测试页面 test.html 放在 templates 目录下
我们需要在测试的html页面中导入命名空间
xmlns:th="http://www.thymeleaf.org"
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<h1>首页<h1>
</body>
</html>
3、启动项目请求测试
在我们没有导入thymeleaf的pom依赖时,我们是访问不到test.html页面的,也就是会出现404错误
在我们导入后,就成功的访问到了页面
10.3 Thymeleaf语法
学习语法,我们在官网找到文档学习即可
thymeleaf:https://www.thymeleaf.org/doc/tutorials/3.0/usingthymeleaf.html#standard-expression-syntax
做个简单测试
10.3.1 测试
1、编写一个TestController
package com.heima.controller;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@Controller
public class IndexController {
@RequestMapping("/test")
public String test(Model model){
model.addAttribute("msg","MessageTest");
return "test";
}
}
2、编写一个测试页面 test.html 放在 templates 目录下
我们需要在测试的html页面中导入命名空间
xmlns:th="http://www.thymeleaf.org"
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<!--/*@thymesVar id="msg" type="com.heima.controller.IndexController"*/-->
<h1 th:text="${msg}"></h1>
</body>
</html>
3、启动项目请求测试
在我们没有导入thymeleaf的pom依赖时,我们是访问不到test.html页面的,也就是会出现404错误
在我们导入后,就成功的访问到了页面
10.4 MVC配置原理
问题:为什么我们在springboot中没有配置视图解析器,但我们仍然进行页面跳转呢?
我们来分析源码....
10.4.1 ContentNegotiatingViewResolver 内容协商视图解析器
我们进入ContentNegotiatingViewResolver 内容协商视图解析器
自动配置了ViewResolver,就是我们之前学习的SpringMVC的视图解析器;
即根据方法的返回值取得视图对象(View),然后由视图对象决定如何渲染(转发,重定向)。
我们去看看这里的源码:我们找到 WebMvcAutoConfiguration , 然后搜索ContentNegotiatingViewResolver。找到如下方法!
@Bean
@ConditionalOnBean(ViewResolver.class)
@ConditionalOnMissingBean(name = "viewResolver", value = ContentNegotiatingViewResolver.class)
public ContentNegotiatingViewResolver viewResolver(BeanFactory beanFactory) {
ContentNegotiatingViewResolver resolver = new ContentNegotiatingViewResolver();
resolver.setContentNegotiationManager(beanFactory.getBean(ContentNegotiationManager.class));
// ContentNegotiatingViewResolver使用所有其他视图解析器来定位视图,因此它应该具有较高的优先级
resolver.setOrder(Ordered.HIGHEST_PRECEDENCE);
return resolver;
}
我们可以点进这类看看!找到对应的解析视图的代码;
@Nullable // 注解说明:@Nullable 即参数可为null
public View resolveViewName(String viewName, Locale locale) throws Exception {
RequestAttributes attrs = RequestContextHolder.getRequestAttributes();
Assert.state(attrs instanceof ServletRequestAttributes, "No current ServletRequestAttributes");
List<MediaType> requestedMediaTypes = this.getMediaTypes(((ServletRequestAttributes)attrs).getRequest());
if (requestedMediaTypes != null) {
// 获取候选的视图对象
List<View> candidateViews = this.getCandidateViews(viewName, locale, requestedMediaTypes);
// 选择一个最适合的视图对象,然后把这个对象返回
View bestView = this.getBestView(candidateViews, requestedMediaTypes, attrs);
if (bestView != null) {
return bestView;
}
}
// .....
}
我们继续点进去看,他是怎么获得候选的视图的呢?
getCandidateViews中看到他是把所有的视图解析器拿来,进行while循环,挨个解析!
Iterator var5 = this.viewResolvers.iterator();
所以得出结论:ContentNegotiatingViewResolver 这个视图解析器就是用来组合所有的视图解析器的
我们再去研究下他的组合逻辑,看到有个属性viewResolvers,看看它是在哪里进行赋值的!
protected void initServletContext(ServletContext servletContext) {
// 这里它是从beanFactory工具中获取容器中的所有视图解析器
// ViewRescolver.class 把所有的视图解析器来组合的
Collection<ViewResolver> matchingBeans = BeanFactoryUtils.beansOfTypeIncludingAncestors(this.obtainApplicationContext(), ViewResolver.class).values();
ViewResolver viewResolver;
if (this.viewResolvers == null) {
this.viewResolvers = new ArrayList(matchingBeans.size());
}
// ...............
}
既然它是在容器中去找视图解析器,我们是否可以猜想,我们就可以去实现一个视图解析器了呢?
我们可以自己给容器中去添加一个视图解析器;这个类就会帮我们自动的将它组合进来;我们去实现一下
10.4.2 自制视图解析器
根据官方文档,我们需要实现一个WebMvcConfigurer接口获得方法,并且加入注释@Configuration,注意这里是不能加入@EnableWebMvc。
package com.heima.controller;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.View;
import org.springframework.web.servlet.ViewResolver;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
import java.util.Locale;
//如果想diy一些定制化功能,只要写这个组件然后交给springboot,springboot就会帮我们自动装配
@Configuration
public class MyMvcConfig implements WebMvcConfigurer {
@Bean
//ViewResolver 实现了视图解析器接口的类,我们就可以把它看作视图解析器
public ViewResolver myViewResolver(){
return new MyViewResolver();
}
//定义了一个视图解析器MyViewResolver
public static class MyViewResolver implements ViewResolver{
@Override
public View resolveViewName(String viewName, Locale locale) throws Exception {
return null;
}
}
}
2.测试我们加入的视图解析器
我们给 DispatcherServlet 中的 doDispatch方法 加个断点进行调试一下,因为所有的请求都会走到这个方法中
3、我们启动我们的项目,然后随便访问一个页面,看一下Debug信息;
找到this
找到视图解析器,我们看到我们自己定义的就在这里了;
所以说,我们如果想要使用自己定制化的东西,我们只需要给容器中添加这个组件就好了!剩下的事情SpringBoot就会帮我们做了!
10.4.3 @EnableWebMvc
但我们在自制的视图解析器中使用这个注解时,springboot就由我们全面接管了。
全面接管即:SpringBoot对SpringMVC的自动配置不需要了,所有都是我们自己去配置!只需在我们的配置类中要加一个@EnableWebMvc。如果我们全面接管了SpringMVC了,那么SpringBoot给我们配置的静态资源映射一定会无效。
为什么会失效呢?进入源码来看看.
1、这里发现它是导入了一个类,我们可以继续进去看
@Import({DelegatingWebMvcConfiguration.class})
public @interface EnableWebMvc {
}
2、它继承了一个父类 WebMvcConfigurationSupport
public class DelegatingWebMvcConfiguration extends WebMvcConfigurationSupport {
// ......
}
3、我们来回顾一下Webmvc自动配置类
@Configuration(proxyBeanMethods = false)
@ConditionalOnWebApplication(type = Type.SERVLET)
@ConditionalOnClass({ Servlet.class, DispatcherServlet.class, WebMvcConfigurer.class })
// 这个注解的意思就是:容器中没有这个组件的时候,这个自动配置类才生效
@ConditionalOnMissingBean(WebMvcConfigurationSupport.class)
@AutoConfigureOrder(Ordered.HIGHEST_PRECEDENCE + 10)
@AutoConfigureAfter({ DispatcherServletAutoConfiguration.class, TaskExecutionAutoConfiguration.class,
ValidationAutoConfiguration.class })
public class WebMvcAutoConfiguration {
}
总结一句话:@EnableWebMvc将WebMvcConfigurationSupport组件导入进来了;
而导入的WebMvcConfigurationSupport只是SpringMVC最基本的功能!
10.5 页面国际化
有时,我们的页面需要多种语言的切换,这时,我们就需要使用页面国际化工具,来配置语言切换功能。
10.5.1 准备工作
1.设置properties文件的编码问题
2.在application.properties中配置i18n乱码解决
#i18n 乱码问题 spring.messages.encoding=UTF-8
10.5.2 使用
1、我们在resources资源文件下新建一个i18n目录,存放国际化配置文件
2、建立一个login.properties文件,还有一个login_zh_CN.properties;
3.我们新建一个其他语言的properties文件,以English为例
4.如下操作即可
接下来我们进行配置的编写
1.我们打开login.properties,点开下面的Resource
2.这里我们可以添加属性
3.添加自己需要的配置然后直接赋值即可
4.去配置文件中查看我们设置的信息
login.properties :默认
login.btn=登录
login.password=密码
login.remember=记住我
login.tip=请登录
login.username=用户名
英文:
login.btn=Sign in
login.password=Password
login.remember=Remember me
login.tip=Please sign in
login.username=Username
中文:
login.btn=登录
login.password=密码
login.remember=记住我
login.tip=请登录
login.username=用户名
5.最后,将自动装配的信息写入application.properties配置文件中
#我们的配置文件的真实位置 spring.messages.basename=i18n.login
6.当我们需要取到相应属性时,#{}即可...
10.6 整合JDBC
10.6.1 SpringData简介
在springboot中,数据访问采用的都是SpringData,springData也是spring中与springboot,springCloud等相当重要的部分。
Sping Data 官网:https://spring.io/projects/spring-data
10.6.2 整合JDBC
1. 新建一个项目,在依赖中选择jdbc有关的依赖
2.完成后打开pow.xml发现为我们导入了相应的依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jdbc</artifactId>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<scope>runtime</scope>
</dependency>
3.之后我们在application.yaml中配置数据库信息,连接数据库
spring:
datasource:
username: root
password: hsp
url: jdbc:mysql://localhost:3306/mybatis?useSSL=false&serverTimezone=UTC&useUnicode=true&characterEncoding=utf8
driver-class-name: com.mysql.cj.jdbc.Driver
type: com.alibaba.druid.pool.DruidDataSource
4.去测试类中测试一下
package com.heima;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import javax.annotation.Resource;
import javax.sql.DataSource;
import java.sql.Connection;
import java.sql.SQLException;
@SpringBootTest
class Springboot05JdbcApplicationTests {
@Resource
DataSource dataSource;
@Test
void contextLoads() throws SQLException {
System.out.println(dataSource.getClass());
//获得数据库连接
Connection connection = dataSource.getConnection();
connection.close();
}
}
5.DataSource
我们可以看到他默认给我们配置的数据源为 : class com.zaxxer.hikari.HikariDataSource , 我们并没有手动配置
我们来全局搜索一下,找到数据源的所有自动配置都在 :DataSourceAutoConfiguration文件:
@Import(
{Hikari.class, Tomcat.class, Dbcp2.class, Generic.class, DataSourceJmxConfiguration.class}
)
protected static class PooledDataSourceConfiguration {
protected PooledDataSourceConfiguration() {
}
}
这里导入的类都在 DataSourceConfiguration 配置类下,可以看出 Spring Boot 2.2.5 默认使用HikariDataSource 数据源,而以前版本,如 Spring Boot 1.5 默认使用 org.apache.tomcat.jdbc.pool.DataSource 作为数据源;
HikariDataSource 号称 Java WEB 当前速度最快的数据源,相比于传统的 C3P0 、DBCP、Tomcat jdbc 等连接池更加优秀;
可以使用 spring.datasource.type 指定自定义的数据源类型,值为 要使用的连接池实现的完全限定名。关于数据源我们并不做介绍,有了数据库连接,显然就可以 CRUD 操作数据库了。但是我们需要先了解一个对象 JdbcTemplate
10.6.3 jdbcTemplate
- JdbcTemplate 的自动配置是依赖 org.springframework.boot.autoconfigure.jdbc 包下的 JdbcTemplateConfiguration 类
- jdbcTemplate是springboot为我们封装好的jdbc,这样我们就可以在一些简单的数据库操作中不使用第三方第数据库操作框架;
- 而springboot又为我们提供了默认的数据源(com.zaxxer.hikari.HikariDataSource);
- 同时默认已经配置好了 JdbcTemplate 放在了容器中,这样我们就可以进行数据库连;
- ,jdbcTemplate为我们提供了操作数据库所需要的CRUD方法,之后就可以进行一系列的CRUD操作数据库了.
JdbcTemplate主要提供以下几类方法:
-
execute方法:可以用于执行任何SQL语句,一般用于执行DDL语句;
-
update方法及batchUpdate方法:update方法用于执行新增、修改、删除等语句;batchUpdate方法用于执行批处理相关语句;
-
query方法及queryForXXX方法:用于执行查询相关语句;
-
call方法:用于执行存储过程、函数相关语句。
测试:
package com.heima.controller;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.ResponseBody;
import javax.annotation.Resource;
import java.util.List;
import java.util.Map;
@Controller
public class JDBCController {
@Resource
JdbcTemplate jdbcTemplate;
@GetMapping("/queryAll")
@ResponseBody
//查询所有用户
public List<Map<String,Object>> queryAll(){
String sql = "select * from mybatis.user";
List<Map<String, Object>> list_maps = jdbcTemplate.queryForList(sql);
return list_maps;
}
@GetMapping("/addUser")
@ResponseBody
//增加一个用户
public String addUser(){
String sql = "insert into mybatis.user(id,name,pwd) values (5,'王五','123123')";
jdbcTemplate.update(sql);
return "add_ok";
}
@GetMapping("/updateUser/{id}")
@ResponseBody
//修改一个用户
public String updateUser(@PathVariable int id){
String sql = "update mybatis.user set name=?,pwd=? where id="+id;
jdbcTemplate.update(sql,"赵强","12315");
return "update_ok";
}
@GetMapping("/deleteUser/{id}")
@ResponseBody
//删除一个用户
public String deleteUser(@PathVariable int id){
String sql = "delete from mybatis.user where id = ?";
jdbcTemplate.update(sql,id);
return "delete_ok";
}
}
CRUD操作可以成功运行,整合JDBC成功!
10.7 整合Mybatis
官方文档:http://mybatis.org/spring-boot-starter/mybatis-spring-boot-autoconfigure/
在springboot中整合mybatis只需要一个maven依赖即可
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>2.1.1</version>
</dependency>
10.7.1 整合测试
1.导入maven依赖
2.配置数据库连接信息(不变)
spring:
datasource:
username: root
password: 123456
#?serverTimezone=UTC解决时区的报错
url: jdbc:mysql://localhost:3306/springboot?serverTimezone=UTC&useUnicode=true&characterEncoding=utf-8
driver-class-name: com.mysql.cj.jdbc.Driver
type: com.alibaba.druid.pool.DruidDataSource
#Spring Boot 默认是不注入这些属性值的,需要自己绑定
#druid 数据源专有配置
initialSize: 5
minIdle: 5
maxActive: 20
maxWait: 60000
timeBetweenEvictionRunsMillis: 60000
minEvictableIdleTimeMillis: 300000
validationQuery: SELECT 1 FROM DUAL
testWhileIdle: true
testOnBorrow: false
testOnReturn: false
poolPreparedStatements: true
#配置监控统计拦截的filters,stat:监控统计、log4j:日志记录、wall:防御sql注入
#如果允许时报错 java.lang.ClassNotFoundException: org.apache.log4j.Priority
#则导入 log4j 依赖即可,Maven 地址:https://mvnrepository.com/artifact/log4j/log4j filters: stat,wall,log4j maxPoolPreparedStatementPerConnectionSize: 20 useGlobalDataSourceStat: true connectionProperties: druid.stat.mergeSql=true;druid.stat.slowSqlMillis=500
3、测试数据库是否连接成功!
4、创建实体类,导入 Lombok!
package com.heima.pojo;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data
@AllArgsConstructor
@NoArgsConstructor
public class User {
private int id;
private String name;
private String pwd;
}
5、创建mapper目录以及对应的 Mapper 接口
UserMapper.java
package com.heima.mapper;
import com.heima.pojo.User;
import org.apache.ibatis.annotations.Mapper;
import org.springframework.stereotype.Repository;
import java.util.List;
@Mapper//这个注解表示了,这是一个mybatis的mapper类
@Repository
public interface UserMapper {
List<User> queryAll();
User queryById(int id);
int addUser(User user);
int updateUser(User user);
int deleteUser(int id);
}
6.在resources目录下创建mybatis目录下创建mapper目录再创建UserMapper.xml文件,编写相应的mybatis的sql语句
7.maven资源过滤问题
<resources>
<resource>
<directory>src/main/java</directory>
<includes>
<include>**/*.xml</include>
</includes>
<filtering>true</filtering>
</resource>
</resources>
8、编写User的 UserController进行测试!
package com.heima.controller;
import com.heima.mapper.UserMapper;
import com.heima.pojo.User;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*;
import javax.annotation.Resource;
import java.util.List;
@Controller
public class UserController {
@Resource
private UserMapper userMapper;
@RequestMapping("/queryAll")
@ResponseBody
public List<User> queryAll(){
List<User> users = userMapper.queryAll();
for (User user : users) {
System.out.println(user);
}
return users;
}
@RequestMapping("/query/{id}")
@ResponseBody
public String queryById(@PathVariable int id){
User user = userMapper.queryById(id);
return user.toString();
}
@RequestMapping("/addUser")
@ResponseBody
public String addUser(){
userMapper.addUser(new User(8,"赵四","12333"));
return "add_Ok";
}
@RequestMapping("/delete/{id}")
@ResponseBody
public String deleteUser(@PathVariable int id){
userMapper.deleteUser(id);
return "delete_ok";
}
@RequestMapping("/update")
@ResponseBody
public String updateUser(User user){
user = new User(4, "陈立农", "123123");
userMapper.updateUser(user);
return "update_ok";
}
}
启动项目访问进行测试!输入对应路径即可得到结果
10.8 集成Swagger
官网:API Documentation & Design Tools for Teams | Swagger
10.8.1 简介
1.前后端分离
-
前端 -> 前端控制层、视图层
-
后端 -> 后端控制层、服务层、数据访问层
-
前后端通过API进行交互
-
前后端相对独立且松耦合
2.产生的问题
-
前后端集成,前端或者后端无法做到“及时协商,尽早解决”,最终导致问题集中爆发
3.解决方案
-
首先定义schema [ 计划的提纲 ],并实时跟踪最新的API,降低集成风险
4.Swagger
-
号称世界上最流行的API框架
-
Restful Api 文档在线自动生成器 => API 文档 与API 定义同步更新
-
直接运行,在线测试API
-
支持多种语言 (如:Java,PHP等)
10.8.2 springboot整合swagger
1.新建一个springboot-web项目
2.导入maven依赖
使用swagger3.0版本,我们需要导入 swagger的相应maven依赖
<dependency> <groupId>org.thingsboard</groupId> <artifactId>springfox-boot-starter</artifactId> <version>3.0.1</version> </dependency>
3.编写HelloController,测试确保运行成功!
4.在properties配置文件中添加
spring.mvc.pathmatch.matching-strategy=ant_path_matcher
5.要使用Swagger,我们需要编写一个配置类-SwaggerConfig来配置 Swagger
@Configuration //配置类
@EnableOpenApi //开启swagger2配置
public class SwaggerConfig {
}
6.配置完之后启动项目访问地址测试:http://localhost:8080/swagger-ui/index.html ,可以看到swagger的界面;
10.8.3 配置swagger
1、Swagger实例Bean是Docket,所以通过配置Docket实例来配置Swaggger。
@Bean //配置docket以配置Swagger具体参数 public Docket docket() { return new Docket(DocumentationType.OAS_30); }
2、可以通过apiInfo()属性配置文档信息
public ApiInfo apiInfo(){ //作者信息 Contact contact = new Contact( "黑麻", "http://baidu.com", "871535508@qq.com"); return new ApiInfo( "黑麻的SwaggerAPI文档", "我是牛马", "v1.0", "http://baidu.com", contact, "Apache 2.0", "http://www.apache.org/licenses/LICENSE-2.0", new ArrayList<>()); }
3、Docket 实例关联上 apiInfo()
@Bean public Docket getDocket(){ return new Docket(DocumentationType.OAS_30) .apiInfo(apiInfo()); }
4、重启项目,访问测试 http://localhost:8080/swagger-ui/index.html
10.8.4 配置扫描接口
1、构建Docket时通过select()方法配置怎么扫描接口。
@Bean public Docket docket() { return new Docket(DocumentationType.OAS_30) .apiInfo(apiInfo()) .select()// 通过.select()方法,去配置扫描接口,RequestHandlerSelectors配置如何扫描接口 .apis(RequestHandlerSelectors.basePackage("com.heima.controller")) .build(); }
2、重启项目测试,由于我们配置根据包的路径扫描接口,所以我们只能看到一个类
3、除了通过包路径配置扫描接口外,还可以通过配置其他方式扫描接口,这里注释一下所有的配置方式:
.select() //RequestHandlerSelectors: 配置要扫描接口的方式 //basePackage: 指定要扫描的包 //any: 扫描全部 //none: 不扫描 //withClassAnnotation: 扫描类上的注解,参数是一个注解的反射对象 //withMethodAnnotation: 扫描方法上的注解 .apis(RequestHandlerSelectors.basePackage("com.heima.controller"))
4、除此之外,我们还可以配置接口扫描过滤:
@Bean public Docket docket() { return new Docket(DocumentationType.OAS_30) .apiInfo(apiInfo()) .select()// 通过.select()方法,去配置扫描接口,RequestHandlerSelectors配置如何扫描接口 .apis(RequestHandlerSelectors.basePackage("com.kuang.swagger.controller")) // 配置如何通过path过滤,即这里只扫描请求以/kuang开头的接口 .paths(PathSelectors.ant("/kuang/**")) .build(); }
5、这里的可选值还有
any() // 任何请求都扫描 none() // 任何请求都不扫描 regex(final String pathRegex) // 通过正则表达式控制 ant(final String antPattern) // 通过ant()控制
10.8.5 swagger开关
1、通过enable()方法配置是否启用swagger,如果是false,swagger将不能在浏览器中访问了
@Bean public Docket getDocket(Environment environment){ return new Docket(DocumentationType.OAS_30) .apiInfo(apiInfo()) .enable(false) // false不启用swagger配置 .groupName("黑麻")//分组命名 .select() //RequestHandlerSelectors: 配置要扫描接口的方式 //basePackage: 指定要扫描的包 //any: 扫描全部 //none: 不扫描 //withClassAnnotation: 扫描类上的注解,参数是一个注解的反射对象 //withMethodAnnotation: 扫描方法上的注解 .apis(RequestHandlerSelectors.basePackage("com.heima.controller")) //过滤扫描的路径 // .paths(PathSelectors.ant("/heima/**")) .build(); }
2、如何动态配置当项目处于test、dev环境时显示swagger,处于prod时不显示?
@Bean public Docket getDocket(Environment environment){ //如何在生产中使用swagger,而发布时不使用呢? //flag = true; //思路:1.判断是生产环境true还是发布环境false //2.enable(flag) //设置要显示的Swagger环境 Profiles pr = Profiles.of("dev", "test"); //获取项目环境,通过environment.acceptsProfiles判断是否处在自己设定的环境中 boolean flag = environment.acceptsProfiles(pr); return new Docket(DocumentationType.OAS_30) .apiInfo(apiInfo()) .enable(flag) // false不启用swagger配置 .groupName("黑麻")//分组命名 .select() //RequestHandlerSelectors: 配置要扫描接口的方式 //basePackage: 指定要扫描的包 //any: 扫描全部 //none: 不扫描 //withClassAnnotation: 扫描类上的注解,参数是一个注解的反射对象 //withMethodAnnotation: 扫描方法上的注解 .apis(RequestHandlerSelectors.basePackage("com.heima.controller")) //过滤扫描的路径 // .paths(PathSelectors.ant("/heima/**")) .build(); }
3、可以在项目中增加一个dev的配置文件查看效果!
server.port=8081
4.输入页面访问路径,发现只有8081端口才能进入到此页面
10.8.6 配置API分组
1、如果没有配置分组,默认是default。通过groupName()方法即可配置分组:
//配置了Swagger的Docket的bean实例 @Bean public Docket getDocket(){ return new Docket(DocumentationType.OAS_30) .apiInfo(apiInfo()) .groupName("黑麻")//分组命名 // 省略配置.... .build(); }
2、重启项目查看分组
3、如何配置多个分组?配置多个分组只需要配置多个docket即可:
@Bean public Docket docket1(){ return new Docket(DocumentationType.OAS_30).groupName("group1"); } @Bean public Docket docket2(){ return new Docket(DocumentationType.OAS_30).groupName("group2"); } @Bean public Docket docket3(){ return new Docket(DocumentationType.OAS_30).groupName("group3"); }
4、重启项目查看即可
10.8.7 实体配置
1、新建一个实体类
package com.heima.pojo;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
@ApiModel("用户实体类")
public class User {
//Swagger中,如果属性的访问修饰符是私有时,必须要有对应的set,get方法,才能扫描到,否则扫描不到实体类信息
@ApiModelProperty("用户名")//给属性加注释
private String username;
@ApiModelProperty("密码")//给属性加注释
private String password;
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;
}
}
2、只要这个实体在请求接口的返回值上(即使是泛型),都能映射到实体项中:
@RequestMapping("/getUser") public User getUser(){ return new User(); }
3、重启查看测试
注:并不是因为@ApiModel这个注解让实体显示在这里了,而是只要出现在接口方法的返回值上的实体都会显示在这里,而@ApiModel和@ApiModelProperty这两个注解只是为实体添加注释的。
@ApiModel为类添加注释
@ApiModelProperty为类属性添加注释
10.8.8 常用注解
Swagger的所有注解定义在io.swagger.annotations包下
下面列一些经常用到的,未列举出来的可以另行查阅说明:
Swagger注解 | 简单说明 |
---|---|
@Api(tags = "xxx模块说明") | 作用在模块类上 |
@ApiOperation("xxx接口说明") | 作用在接口方法上 |
@ApiModel("xxxPOJO说明") | 作用在模型类上:如VO、BO |
@ApiModelProperty(value = "xxx属性说明",hidden = true) | 作用在类方法和属性上,hidden设置为true可以隐藏该属性 |
@ApiParam("xxx参数说明") | 作用在参数、方法和字段上,类似@ApiModelProperty |
我们也可以给请求的接口配置一些注释
@ApiOperation("黑麻") @PostMapping("/heima") @ResponseBody public String kuang(@ApiParam("这个名字会被返回")String username){ return username; }
这样的话,可以给一些比较难理解的属性或者接口,增加一些配置信息,让人更容易阅读!
Swagger是个优秀的工具,现在国内已经有很多的中小型互联网公司都在使用它,相较于传统的要先出Word接口文档再测试的方式,显然这样也更符合现在的快速迭代开发行情。当然了,提醒下大家在正式环境要记得关闭Swagger,一来出于安全考虑二来也可以节省运行时内存。