简单说下SpringBoot吧(重点)
springboot是spring开源组织下的子项目,是spring的一站式解决方案,简化了使用spring的难度,简化了繁琐的配置,提供许多启动器(starter),使开发者能快速上手。
开发小技巧
lombok
简化javabean开发,自动生成get/set方法、有参/无参构造方法、toString()、equals()、hashcode()方法等。
引入lombok依赖:
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
安装lombok插件:
在idea的plugin市场里安装lombok插件
spring initailizr
快速创建springboot项目,项目结构、依赖啥的都帮助创建好。
dev-tools
对修改的项目重新编译,使用快捷键crtl+F9
引入依赖:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<optional>true</optional>
</dependency>
配置文件yaml用法
基本语法
- key: value k-v之间有空格
- 大小写敏感
@ConfigurationProperties
作用地方:作用在类上
作用:将bean对象跟.yaml或.properties配置文件进行绑定
属性:prefix,将bean对象跟配置文件前缀下面的内容进行绑定
实例及用法
自定义类绑定的配置提示
在yml或properties配置文件中进行相关配置时,能够对自定义的类进行提示
引入依赖:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
<optional>true</optional>
</dependency>
对项目进行打包的时候去除不相关的jar包
web开发
静态资源访问
静态资源目录
只要静态资源放在类路径下:/static(or /public or /resources or /META-INF/resources)
访问:当前项目根目录/+静态资源名
原理:静态资源映射的是/**(即拦截所有请求),动态资源也是拦截所有请求,请求进来先去找controller(动态资源)看能不能处理,如果不能处理,交给静态资源处理器,静态资源按照上面的目录去找,如果找不到就返回404
配置静态资源访问前缀
默认无前缀
添加前缀:
#添加resources前缀,访问路径变成localhost:8080/resources/aaaaa.jpg
spring:
mvc:
static-path-pattern: /resources/**
配置静态资源类路径
源码:
public class ResourceProperties {
private static final String[] CLASSPATH_RESOURCE_LOCATIONS = new String[]{
"classpath:/META-INF/resources/", "classpath:/resources/", "classpath:/static/", "classpath:/public/"};
private String[] staticLocations;
private boolean addMappings;
private final ResourceProperties.Chain chain;
private final ResourceProperties.Cache cache;
分析源码可以发现静态资源类路径默认有"classpath:/META-INF/resources/", "classpath:/resources/", "classpath:/static/", "classpath:/public/"
这些,如果还想增加类路径,可以通过配置进行。
applicatin.yml:
#将静态资源放到haha目录下,组数类型可以设置多个类路径
spring:
resources:
static-locations: [classpath:/haha/]
webjar(了解)
将静态资源如:js、image、css等打成jar包
欢迎页支持
将欢迎页index.html放入静态资源类路径下放,访问路径localhost:8080
- 可以配置静态资源类路径
- 不可以配置静态资源访问前缀,否则导致欢迎页不能访问
favicon图标
将图标放入静态资源类路径下,访问页面的时候就会出现图标
- 不可以配置静态资源访问前缀
- 不可以配置静态资源类路径会
静态资源配置原理
- springboot启动默认加载XXXXAutoConfiguration类(自动配置类)
- springmvc功能的自动配置类WebMvcAutoConfiguration,生效
- …
请求参数处理
rest映射及源码解析
请求映射原理
请求处理常用注解(重点)
各种类型参数解析原理
model、map原理
自定义参数绑定原理
自定义converter原理
returnvaluehandler原理
httpmessageconverter原理
内容协商原理
基于请求参数的内容协商原理
自定义messageconverter
视图解析与模板引擎
视图解析:springboot默认不支持jsp,需要引入第三方模板引擎实现页面渲染。如:freemarker、groovy-templates、thymeleaf
thymeleaf是应用于后端服务器上的模板引擎,语法简单上手快适合单体开发,但是不适用高并发的项目开发,如果要开发高并发项目还是要采用前后端分离技术。
视图解析器和视图原理
thymeleaf的使用
引入thymeleaf依赖:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
引入thymeleaf的名称空间:
xmlns:th="http://www.thymeleaf.org"
thymeleaf基本语法
-
表达式
-
字面量
-
数学运算
运算符:+,-,*,/,% -
布尔运算
运算符:and,or
一元运算:!,not -
比较运算
比较:>,<,>=,<=(gt,lt,ge,le)
等式:==,!=(eq,ne) -
条件运算
案例:
整合thymeleaf构建后台管理系统
项目结构图:
登录功能
初步登录框架
重定向解决表单重复提交问题,后面刷新的就是main.html页面不再是重复提交表单了。
登录拦截及登录密码错误提示
未登录直接访问main.html页面,进行拦截并提示;账号密码错误进行提示
登录名动态显示
thymeleaf引入公共页面
这些页面的公共部分有:顶部和侧边栏,因此引入页面的顶部和侧边栏。
- 首先在templates底下新建一个com文件,用来存放侧边栏和顶部公共代码文件
顶部head.html
<!DOCTYPE HTML>
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:th="http://www.thymeleaf.org">
<head>
<footer th:fragment="common_head">
....(此处为顶部公共部分代码,省略五百行)
</footer>
</head>
</html>
侧边栏side.html
<!DOCTYPE HTML>
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:th="http://www.thymeleaf.org">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<footer th:fragment="common_side">
<div class="menu">
.......(此处为侧边栏公共部分代码,省略五百行)
</div>
</footer>
</head>
</html>
- 现在假设我在写用户界面的模块,只需要在固定位置引入以上两个文件即可
拦截器
步骤:
- 编写一个拦截器实现HandlerInterceptor接口
- 将拦截器注册到容器中(实现WebMvcConfigurer接口的addInterceptors()方法)
- 指定拦截规则
初步拦截框架:
拦截跳转并提示:
拦截器配置好项目一启动,拦截器就开始工作,/**能拦截所有请求,但是会放行一些静态资源,当用户登录了它就放行不进行拦截,没有登录就进行拦截。
拦截器执行流程分析:
细节:拦截器中拦截的资源没有登录不能访问,放行的资源不用登录也能访问
拦截器原理
文件上传功能
文件上传框架初步搭建
文件上传完整功能
浏览器发送提交请求后,服务器接收请求,将文件存储到文件服务器中
文件上传原理
springboot异常处理机制
默认规则
- 默认情况下,springboot提供/error处理所有的错误映射
- 对于机器客户端,它将生成JSON响应,其中包含错误,HTTP状态和异常信息的详细信息。对于浏览器客户端,响应一个whitelable错误视图,以HTML格式呈现相同的数据
- 要对其进行自定义,添加view解析为error
- 要完全替换默认行为,可以实现ErrorController并注册该类型bean定义,或添加ErrorAttribute类型的组件以使用现有机制但替换其内容
定制错误处理逻辑
-
error/下的4xxx、5xxx页面会被自动解析;有精确的错误状态码页面就精确匹配,没有就找4xxx.html;如果都没有就触发whitelabel
-
@ControllerAdvice+@ExceptionHandler处理全局异常(推荐使用)
@ControllerAdvice
作用位置:类上
作用:类似于@component注解,创建bean对象并注入springioc核心容器中
属性:value,指定bean的id,当我们不写时它的默认值是当前类名,且首字母改小写。@ExceptionHandler
作用位置:方法上
作用:处理异常
属性:value,指定所能处理异常的字节码,当只有一个属性时默认可以不写属性名。 -
@ResponseStatus+自定义异常;
@ResponseStatus
作用地方:类上
作用:指定异常的状态和原因
属性:value指定异常状态;reason指定异常出现原因
静态资源类路径异常处理功能
将4XXX和5XXX放在templates目录下的error目录下,自动解析页面
DefaultErrorAttributes源码:
该源码中包含错误页面可以包含的属性
public class DefaultErrorAttributes implements ErrorAttributes {
public Map<String, Object> getErrorAttributes(ServerRequest request, ErrorAttributeOptions options) {
Map<String, Object> errorAttributes = this.getErrorAttributes(request, options.isIncluded(Include.STACK_TRACE));
if (Boolean.TRUE.equals(this.includeException)) {
options = options.including(new Include[]{
Include.EXCEPTION});
}
if (!options.isIncluded(Include.EXCEPTION)) {
errorAttributes.remove("exception");
}
if (!options.isIncluded(Include.STACK_TRACE)) {
errorAttributes.remove("trace");
}
if (!options.isIncluded(Include.MESSAGE) && errorAttributes.get("message") != null) {
errorAttributes.put("message", "");
}
if (!options.isIncluded(Include.BINDING_ERRORS)) {
errorAttributes.remove("errors");
}
return errorAttributes;
}
/** @deprecated */
@Deprecated
public Map<String, Object> getErrorAttributes(ServerRequest request, boolean includeStackTrace) {
Map<String, Object> errorAttributes = new LinkedHashMap();
errorAttributes.put("timestamp", new Date());
errorAttributes.put("path", request.path());
Throwable error = this.getError(request);
MergedAnnotation<ResponseStatus> responseStatusAnnotation = MergedAnnotations.from(error.getClass(), SearchStrategy.TYPE_HIERARCHY).get(ResponseStatus.class);
HttpStatus errorStatus = this.determineHttpStatus(error, responseStatusAnnotation);
errorAttributes.put("status", errorStatus.value());
errorAttributes.put("error", errorStatus.getReasonPhrase());
errorAttributes.put("message", this.determineMessage(error, responseStatusAnnotation));
errorAttributes.put("requestId", request.exchange().getRequest().getId());
this.handleException(errorAttributes, this.determineException(error), includeStackTrace);
return errorAttributes;
}
@controlleradvice+@exceptionhandler处理全局异常功能
@ResponseStatus+自定义异常
异常处理自动配置原理
异常处理流程
web原生组件注入(servlet、listener、filter)
-
使用servlet API方式
@ServletComponentScan
作用地方:springboot的启动类上
作用:springboot的启动类上@servletcomponentscan注解后,servlet、filter、listener可以直接通过@webservlet、@webfilter、@weblistener注解自动注册
属性:value指定要扫描的包@webservlet
作用地方:定义的servlet类上
作用:建立发送请求映射路径url,等价于web.xml中的<servlet></servlet><servlet-mapping></servlet-mapping>中的配置
@webfilter
作用地方:定义的filter类上
作用:设置要过滤路径,等价于web.xml中的<filter></filter><filter-mapping></filter-mapping>
中的配置
@weblistener
作用地方:定义的listener类上
作用:对项目进行监听,监听项目初始化完成和项目销毁等
实例分析
servlet:
filter:
listener:
- 用ServletRegistrationBean,FilterRegistrationBean,ServletListenerRegistrationBean方式
@Slf4j
public class MyServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
resp.getWriter().write("66666");
}
}
@Slf4j
public class MyFilter implements Filter {
@Override
public void init(FilterConfig filterConfig) throws ServletException {
log.info("MyFilter初始化完成");
}
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
log.info("MyFilter工作");
chain.doFilter(request,response);
}
@Override
public void destroy() {
log.info("MyFilter销毁");
}
}
@Slf4j
public class MySwervletContextListener implements ServletContextListener {
@Override
public void contextInitialized(ServletContextEvent sce) {
log.info("MySwervletContextListener监听到项目初始化完成");
}
@Override
public void contextDestroyed(ServletContextEvent sce) {
log.info("MySwervletContextListener监听到项目销毁");
}
}
@Configuration(proxyBeanMethods = true) //保证依赖的组件始终是单实例的
public class MyRegistConfig {
@Bean
public ServletRegistrationBean myServlet(){
MyServlet myServlet = new MyServlet();
return new ServletRegistrationBean(myServlet,"/my","/my02");
}
@Bean
public FilterRegistrationBean myFilter(){
MyFilter myFilter = new MyFilter();
// return new FilterRegistrationBean(myFilter,myServlet());
FilterRegistrationBean filterRegistrationBean = new FilterRegistrationBean(myFilter);
filterRegistrationBean.setUrlPatterns(Arrays.asList("/my","/css/*"));
return filterRegistrationBean;
}
@Bean
public ServletListenerRegistrationBean myListener(){
MySwervletContextListener mySwervletContextListener = new MySwervletContextListener();
return new ServletListenerRegistrationBean(mySwervletContextListener);
}
}
运行结果同上面使用@websevlet、@webfilter、@weblistener、@ServletComponentScan一样
DispacherServlet注入原理
嵌入式servlet容器
- 默认支持的webserver
tomcat、undertow、jetty、netty - 切换服务器
数据访问
数据源的自动配置(默认的HiKariDataSource)
导入jdbc依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jdbc</artifactId>
</dependency>
为什么导入JDBC依赖,官方不导入数据库依赖呢?因为官方不知道我们要操作什么数据库。
数据库依赖版本要和操作数据库版本对应
想要修改版本
- 引入依赖的时候引入具体版本
- 重新声明版本
分析自动配置
自动配置类
- DataSourceAutoConfiguration:数据源的自动配置
修改数据源相关的配置:spring.datasource
数据库连接池的配置,是自己容器中没有datasource才自动配置
底层配置好的连接池是:HikaiDataSource
DataSourceTransactionManagerAutoConfiguration:事务管理器的自动配置
JdbcTemplateAutoConfiguration:JdbcTemplate的自动配置,可以对数据库进行crud
JndiDataSourceAutoConfiguration:jndi的自动配置
XADataSourceAutoConfiguration:分布式事务相关的自动配置
使用Druid数据源
引入Druid数据源
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.1.17</version>
</dependency>
整合第三方技术的两种方式:
- 自定义方式
@ConfigurationProperties
作用地方:类和方法上
作用:批量将applicaiton.properties或者application.yaml配置文件中的属性值注入对象实例中,常用于数据源读写分离场景中。
属性:prefix前缀,指定一个前缀就可以将带有这一类前缀的属性进行注入实例中。
切换到druid数据源:
加入druid数据源的监控和防火墙功能:
/**
* 配置 druid的监控页功能
* @return
*/
@Bean
public ServletRegistrationBean statViewServlet(){
StatViewServlet statViewServlet = new StatViewServlet();
ServletRegistrationBean<StatViewServlet> registrationBean = new ServletRegistrationBean<>(statViewServlet, "/druid/*");
registrationBean.addInitParameter("loginUsername","admin");
registrationBean.addInitParameter("loginPassword","123456");
return registrationBean;
}
/**
* WebStatFilter 用于采集web-jdbc关联监控的数据。
*/
@Bean
public FilterRegistrationBean webStatFilter(){
WebStatFilter webStatFilter = new WebStatFilter();
FilterRegistrationBean<WebStatFilter> filterRegistrationBean = new FilterRegistrationBean<>(webStatFilter);
filterRegistrationBean.setUrlPatterns(Arrays.asList("/*"));
filterRegistrationBean.addInitParameter("exclusions","*.js,*.gif,*.jpg,*.png,*.css,*.ico,/druid/*");
return filterRegistrationBean;
}
- 引入官方druid的start依赖方式
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid-spring-boot-starter</artifactId>
<version>1.1.17</version>
</dependency>
配置druid数据源的监控和防火墙功能:
使用applicaiton.yml配置文件来对druid的监控和防火墙进行配置
spring:
datasource:
url: jdbc:mysql://localhost:3306/mydb3?useSSL=false
username: root
password: 636895
driver-class-name: com.mysql.jdbc.Driver
druid:
aop-patterns: com.atguigu.admin.* #springbean监控
filters: stat,wall,slf4j #所有开启的功能,stat(sql监控),wall(防火墙)
stat-view-servlet: #监控页配置
enabled: true
login-username: admin
login-password: admin
resetEnable: false
web-stat-filter: #web监控
enabled: true
urlPattern: /*
exclusions: '*.js,*.gif,*.jpg,*.png,*.css,*.ico,/druid/*'
filter:
stat: #sql监控,对上面filter里面的stat的详细配置
slow-sql-millis: 1000
logSlowSql: true
enabled: true
wall: #防火墙
enabled: true
config:
drop-table-allow: false
public class MyDataSourceConfig {
public DataSource dataSource() throws SQLException {
DruidDataSource druidDataSource = new DruidDataSource();
return druidDataSource;
}
springboot整合mybatis操作
引入mybatis的启动器依赖:
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>2.1.4</version>
</dependency>
配置模式
表现层调用业务层,业务层调用持久层;在表现成中注入业务层,在业务层中注入持久层;需要全局配置文件xml和映射配置文件xml,但是全局配置文件可以使用yml配置文件代替。
@Mapper注解
作用地方:持久层的接口上
作用:编译时生成该接口的实现类,需要注意的是:这个接口中不可以定义同名的方法,因为会生成相同的id 也就是说这个接口是不支持重载的
@MapperScan注解
作用地方:springboot的启动类上
作用: 指定要变成实现类的接口所在的包,然后包下面的所有接口在编译之后都会生成相应的实现类
注解模式
混合模式
混合模式,注解和xml映射配置文件一起使用,简单sql语句用注解,复杂查询用映射配置文件xml;全局配置文件xml可以使用yml配置文件进行代替,很多配置可以直接在yml中指定。
springboot整合mybatis-plus操作数据库
mybatis-plus是mybatis的增强版,在mybatis的基础上只做增强不做改变,为简化开发、提高效率而生。
mybatis-plus给我们提供了一个basemapper接口它是一个泛型,要操作哪个类型数据就填入哪个泛型,basemapper里面给我们提供了很多crud的方法,使用它对于一般简单的crud操作我们不需要再写xml映射配置文件或者crud注解来进行sql语句编写,直接使用它提供的方法即可;除非是一个复杂的sql语句已经不能使用它提供的方法了,我们才需要自己编写xml映射配置文件或者crud注解来自己写sql语句。反观mybatis需要自己使用xml映射配置文件或者crud注解来进行sql语句的编写,这对于sql语句的编写能力有一定要求;mybatis-plus简单方便,具有通用CRUD操作。
安装mybatisX快速开发插件
- 可以快速在接口和xml映射配置文件之间来回跳转很方便
- 连接数据库逆向生成代码
- 愈发提示
引入依赖mybatis-plus:
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>3.4.1</version>
</dependency>
分析自动配置
…
基础实例
测试类中注入持久层,持久层继承BaseMapper接口,该接口由mybatis-plus提供,里面有很多CRUD方法,由持久层去调用CRUD方法。
细节:默认情况下mybatis-plus去找实体类名和数据库表名一致的数据表进行操作,如果实体类名和数据表名不一致就会报错,需要指定表名了。
@TableField
作用地方:实体类属性上
属性:exist,指定标注的实体类属性在数据库表中不出现
@TableName
作用地方:实体类上
属性:value,指定要操作的数据库中的数据表
完整实例
表现层中注入业务层,由于业务层Iservice跟BaseMapper很相似也提供很多crud方法,业务层中并没有注入持久层,由业务层去调用curd方法
视图进行页面渲染,对表格进行遍历
分页功能
细节:参数上添加了@requestparam注解,现在URL是localhost:8080/dynamic_table?pn=xxx
删除功能
从当前页面删除用户之后依然跳转到当前页面,使用重定向RedirectAttritute携带请求参数(当前页)
细节:因为添加了@requestparam注解,URL是localhost:8080/user/delete/xxx?pn=xxx
springboot整合redis
Redis是一个开源的基于内存中的数据结构存储系统,它可以用作数据库、缓存和消息中间件;它支持多种类型的数据结构,如字符串、散列(hash)、列表(list)、集合、有序集合与范围查询、bitmaps、hyperloglog和地理空间(geospatial) 。Redis 内置了复制、LUA脚本、LRU驱动事件、事务和不同级别的磁盘持久化,并通过 Redis 哨兵(Sentinel) 和自动分区(Cluster)提供高可用性(high availability)。
导入redis的启动器依赖:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
redis的自动配置
- RedisAutoConfiguration自动配置类。RedisProperties属性类通过spring.redis.xxx对redis进行配置。
- java连接redis有2个客户端,LettuceConnectionConfiguration、JedisConnectionConfiguraion
- 自动注入RedisTemplate<Object,Object>:
- 自动注入StringRedisTemplate;k-v都是string
- 底层只要使用了RedisTemplate、StringRedisTemplate就可以操作redis,跟JdbcTemplate类似,它可以操作数据库进行crud操作。
阿里云redis环境搭建
- 创建redis实例并进行相关配置(如:商品类型、地域、网络类型、版本类型、版本号等)
- 开启公网连接地址
- 修改白名单ip地址
- 账户是否要重新创建等
细节:阿里云redis实例密码为用户名:密码
redis连接java(使用Lettuce客户端)
切换成jedis客户端进行java和redis连接
方式一:排序lettuce依赖并引入jedis依赖
方式二:不使用排除的方式,在yml配置文件中指定指定客户端类型
使用redis统计当前请求路径范文次数
springboot整合junit
junit5的变化
springboot2.2.0版本开始引入junit5作为单元测试默认库,junit5由3个不同模块组成。
junit5=junit plateform+junit jupiter+junit vintage
细节:springboot2.4以上版本移除了对vintage的依赖,如果需要兼容junit4需要自行导入。
<dependency>
<groupId>org.junit.vintage</groupId>
<artifactId>junit-vintage-engine</artifactId>
<scope>test</scope>
<exclusions>
<exclusion>
<groupId>org.hamcrest</groupId>
<artifactId>hamcrest-core</artifactId>
</exclusion>
</exclusions>
</dependency>
引入junit5启动器依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
junit5常用注解
@DisplayName
作用地方:测试类上或者测试方法上
属性:value,为测试类或测试方法设置展示名称
@BeforeEach
作用地方:目标方法上
作用:在每个单元测试之前执行
@AfterEach
作用地方:目标方法上
作用:在每个单元测试之后执行
@BeforeAll
作用地方:目标方法上
作用:在所有单元测试之前执行
@AfterAll
作用地方:在目标方法上
作用:在所有单元测试之后执行
@Disable
作用地方:测试类上或测试方法上
作用:表示测试类或者测试方法不执行
@Timeout
作用地方:测试方法上
属性:value和unit,指定超时时间和单位。超过超时时间后方法不执行
@SpringBootTest
作用地方:测试类上
作用:将测试类与springboot进行整合
@RepeatedTest
作用地方:测试方法上
属性:value,执行方法重复执行的次数
断言
断言是测试方法的核心部分,用来对测试需要满足的条件进行验证,检查业务逻辑返回的数据是否合理。这些断言方法都是org.junit.jupiter.api.Assertions的静态方法。
简单断言
方法 | 说明 |
---|---|
assertEquals | 判断两个对象或两个原始类型是否相等 |
assertNotEquals | 判断两个对象或两个原始类型是否不相等 |
assertSame | 判断两个对象引用是否指向同一对象 |
assertNotSame | 判断两个对象引用是否指向不同对象 |
assertTrue | 判断给定的布尔值是否为true |
assertFalse | 判断给定的布尔值是否为false |
assertNull | 判断给定的对象引用是否为null |
assertNotNull | 判断给定的对象引用是否不为null |
细节:前面断言失败,后面代码都不回执行
数组断言
通过assertArrayEquals方法来判断两个对象或原始类型的数组是否相等
组合断言
assertAll方法接受多个Executable函数式接口的实例作为要验证的断言,可以通过lambda表达式很容易的提供这些断言。
细节:声明的所有断言全部成功,才能继续往下执行
异常断言
assertThrows()方法,配合函数式编程使用。
超时断言
assertTimeout()为测试方法设置超时时间
快速失败
前置条件
前置条件类似于断言,不同之处在于不满足的断言会使得测试方法失败,而不满足的前置条件会使得测试方法执行终止。
嵌套测试
…
参数化测试
参数化测试junit5很重要的一个新特性,它使得用不同参数进行多次单元测试成为了可能,而不需要每新增一个参数就新增一个单元测试,省去了很多冗余代码。
以下注解都是使用在测试方法上的
- @ParameterizedTest:指定该方法为参数化测试方法
- @ValueSource:为参数化测试提供入参来源,支持基本数据类型、String类型以及应用类型。
- @NullSource:为参数化测试提供一个null入参。
- @EnumSource:为参数化测试提供一个枚举入参。
- @CsvFileSource:表示读取指定csv文件内容作为参数化测试的入参。
- @MethodSource:表示读取指定方法的返回值作为参数化测试的入参(注意:方法返回需要是一个流)。
指标监控
springboot Actuator
简介
未来每个微服务部署在云上后,我们都需要对其进行监控、追踪、审计、控制等。springboot就抽取了Actuator场景,使得我们每个微服务快速引用即可获得生产级别的引用监控、审计等功能。
引入actuator启动器依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
如何使用
访问地址:localhost:8080/actuator
开启所有访问断点:
management:
endpoints:
enabled-by-default: true #默认开启所有监控端点 true
web:
exposure:
include: '*' # 以web方式暴露所有端点
最常使用的断点
@SpringBootApplication
作用地方:springboot启动类上
属性:exclude,指定移除那个类的功能
定制endpoint
…
服务器对客户端监控可视化配置
- 创建监控服务器对客户端进行监控
- 在监控服务器中引入admin-server启动器依赖
<dependency>
<groupId>de.codecentric</groupId>
<artifactId>spring-boot-admin-starter-server</artifactId>
<version>2.3.1</version>
</dependency>
- 在监控服务器启动类上加上@EnableAdminServer注解,开启监控服务功能
- 修改监控服务器端口为8888
- 在客户端中引入admin-clinet启动器依赖
<dependency>
<groupId>de.codecentric</groupId>
<artifactId>spring-boot-admin-starter-client</artifactId>
<version>2.3.1</version>
</dependency>
- 在客户端中配置数据要汇报的服务器地址
boot:
admin:
client:
url: http://localhost:8888 #相当于客户端把数据汇报到哪个服务器
SpringBoot高级特性
Profile功能
如果将来项目有开发环境(dev),还有测试环境(test)、生产环境(prod),为了方便多环境适配,可以使用profile功能切换项目到项目需要的环境。
实例
- 使用application.properties配置文件对环境进行切换
- 使用命令行的方式对环境进行切换
java -jar xxxx.jar --spring.profiles.active=test
java -jar xxxx.jar --spring.profiles.active=test --person.name=hello
在打包后依然想要切换环境,可以在命令行中使用命令执行。
@Profile注解
作用地方:类或方法上
属性:value,指定激活哪种环境
功能:
- 条件装配功能
- profile分组功能