前言
本节内容主要是对webflux项目一些常用功能的介绍,例如系统集成swagger接口文档,方便接口测试以及前后端项目联调测试;使用actuator完成系统各种指标的监控功能;系统使用logback日志框架完成项目日志的收集;使用过滤器WebFilter完成一些初始化验证;使用CorsWebFilter解决系统的跨域问题;使用AOP切面实现功能方法操作日志的打印等。
正文
swagger接口文档集成
①引入webflux的springdoc文档的pom依赖
<!-- https://mvnrepository.com/artifact/org.springdoc/springdoc-openapi-starter-webflux-ui -->
<dependency>
<groupId>org.springdoc</groupId>
<artifactId>springdoc-openapi-starter-webflux-ui</artifactId>
<version>2.3.0</version>
</dependency>
②在资源文件application.yaml中配置接口文档访问地址,并开启接口文档访问权限enabled: true,生产环境可以关闭
springdoc:
api-docs:
enabled: true
path: /api-docs
swagger-ui:
enabled: true
path: /swagger-ui/index.html
show-actuator: true
③访问swagger文档地址,查看集成效果
④更高级的用法, 通过配置GroupedOpenApi分组,定义不同的分组匹配规则,配置更细粒度的接口分组文档
package com.yundi.atp.config;
import io.swagger.v3.oas.models.ExternalDocumentation;
import io.swagger.v3.oas.models.OpenAPI;
import io.swagger.v3.oas.models.info.Info;
import io.swagger.v3.oas.models.info.License;
import org.springdoc.core.models.GroupedOpenApi;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class SpringDocConfig {
@Bean
public GroupedOpenApi sysOpenApi() {
return GroupedOpenApi.builder()
.group("SpringWebflux-系统管理")
.pathsToMatch("/user/**", "/role/**")
.build();
}
@Bean
public GroupedOpenApi actuatorOpenApi() {
return GroupedOpenApi.builder()
.group("SpringWebflux-系统监控")
.pathsToMatch("/actuator/**")
.build();
}
@Bean
public OpenAPI springDocOpenAPI() {
return new OpenAPI()
.info(new Info().title("SpringWebflux API")
.description("SpringWebflux 案例")
.version("v1.0.0")
.license(new License().name("Apache 2.0").url("http://springdoc.org")))
.externalDocs(new ExternalDocumentation()
.description("SpringWebflux Wiki Documentation")
.url("https://springshop.wiki.github.org/docs"));
}
}
⑤接口文档分组效果,可根据Select a definition切换到不同的文档分组下
actuator监控配置
①引入actuator监控启动器的pom依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
②在资源配置文件application.yaml中配置actuator监控的web访问
management:
endpoints:
enabled-by-default: true #暴露所有端点信息
web:
exposure:
include: '*' #以web方式暴露
③通过swagger接口文档,查看actuator监控的web指标接口
logback日志配置
①在resources资源目录下创建一个logback.xml日志文件,定义日志文件的打印格式及规则等
<?xml version="1.0" encoding="UTF-8"?>
<configuration debug="false">
<!--设置存储路径变量-->
<property name="LOG_HOME" value="ht-webflux"/>
<!--控制台输出appender-->
<appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender">
<!--设置输出格式-->
<encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
<!--格式化输出:%d表示日期,%thread表示线程名,%-5level:级别从左显示5个字符宽度,%msg:日志消息,%n是换行符-->
<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n</pattern>
<!--设置编码-->
<charset>UTF-8</charset>
</encoder>
</appender>
<!--文件输出,时间窗口滚动-->
<appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
<!--日志名,指定最新的文件名,其他文件名使用FileNamePattern -->
<File>${LOG_HOME}/ht.log</File>
<!--文件滚动模式-->
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<!--日志文件输出的文件名,可设置文件类型为gz,开启文件压缩-->
<FileNamePattern>${LOG_HOME}/%d{yyyy-MM-dd}_%i.log</FileNamePattern>
<!--日志文件保留天数-->
<MaxHistory>30</MaxHistory>
<!--按大小分割同一天的-->
<timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
<maxFileSize>20MB</maxFileSize>
</timeBasedFileNamingAndTriggeringPolicy>
</rollingPolicy>
<!--输出格式-->
<encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
<!--格式化输出:%d表示日期,%thread表示线程名,%-5level:级别从左显示5个字符宽度%msg:日志消息,%n是换行符-->
<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n</pattern>
<!--设置编码-->
<charset>UTF-8</charset>
</encoder>
</appender>
<!--根据环境配置日志-->
<springProfile name="dev">
<!-- 打印 日志级别 -->
<root level="INFO">
<appender-ref ref="CONSOLE"/>
<appender-ref ref="FILE"/>
<!-- <appender-ref ref="LOGSTASH"/>-->
</root>
</springProfile>
<springProfile name="test">
<!-- 打印 日志级别 -->
<root level="INFO">
<appender-ref ref="CONSOLE"/>
<appender-ref ref="FILE"/>
</root>
</springProfile>
<springProfile name="prod">
<!--指定基础的日志输出级别-->
<root level="INFO">
<!--appender将会添加到这个logger-->
<appender-ref ref="CONSOLE"/>
<appender-ref ref="FILE"/>
<!-- <appender-ref ref="LOGSTASH"/>-->
</root>
</springProfile>
</configuration>
②启动项目,查看日志输出
过滤器WebFilter整合
①通过实现WebFilter接口,定义一个自定义的web过滤器MyWebFilter,并加入spring容器中
package com.yundi.atp.filter;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.http.server.reactive.ServerHttpResponse;
import org.springframework.stereotype.Component;
import org.springframework.web.server.ServerWebExchange;
import org.springframework.web.server.WebFilter;
import org.springframework.web.server.WebFilterChain;
import reactor.core.publisher.Mono;
@Component
@Slf4j
public class MyWebFilter implements WebFilter {
@Override
public Mono<Void> filter(ServerWebExchange exchange, WebFilterChain chain) {
//可以获取请求域
ServerHttpRequest request = exchange.getRequest();
log.info("url:", request.getURI());
//可以获取响应域
ServerHttpResponse response = exchange.getResponse();
log.info("--------------请求处理放行到目标方法之前的过滤器业务处理------------");
Mono<Void> filter = chain.filter(exchange);
//流一旦经过某个操作就会变成新流
Mono<Void> mono = filter.doOnError(error -> {
log.info("---------------目标方法异常以后--------------");
log.info("error:" + error);
}).doFinally(signalType -> {
log.info("---------------目标方法执行完成以后--------------");
});
return mono;
}
}
②访问任意一个接口,查看web过滤器是否生效
CorsWebFilter跨域配置
①配置CorsWebFilter过滤器,解决接口请求跨域问题
package com.yundi.atp.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.cors.reactive.CorsWebFilter;
import org.springframework.web.cors.reactive.UrlBasedCorsConfigurationSource;
@Configuration
public class MyCorsConfig {
@Bean
public CorsWebFilter corsWebFilter() {
CorsConfiguration corsConfig = new CorsConfiguration();
// 允许所有来源
corsConfig.addAllowedOrigin("*");
// 允许所有HTTP方法
corsConfig.addAllowedMethod("*");
// 允许所有请求头
corsConfig.addAllowedHeader("*");
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
source.registerCorsConfiguration("/**", corsConfig);
return new CorsWebFilter(source);
}
}
②查看浏览器响应头中是否包含跨域配置
AOP切面
①创建一个操作日志的OperateLogAspect切面,记录请求方法执行过程日志
package com.yundi.atp.aop;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.stereotype.Component;
import reactor.core.publisher.Mono;
@Slf4j
@Aspect
@Component
public class OperateLogAspect {
/**
* 切点
*/
@Pointcut("execution(* com.yundi.atp.controller.*.*(..))")
public void logPointCut() {
}
@Around("logPointCut()")
public Mono<Object> aroundAdvice(ProceedingJoinPoint joinPoint) throws Throwable {
// 在方法执行前的逻辑
log.info("************************目标方法执行前************************");
log.info("args:{}",joinPoint.getArgs());
// 执行被切入的方法
Mono<Object> result = (Mono<Object>) joinPoint.proceed();
// 在方法执行后的逻辑
Mono<Object> mono = result.doOnError(error -> {
log.info("************************目标方法异常以后************************");
log.info("error:" + error);
}).doFinally(signalType -> {
log.info("************************目标方法执行完成以后************************");
});
return mono;
}
}
② 访问接口,验证操作日志切面是否生效
结语
关于springboot3下WebFlux项目的一些常用功能整合的内容到这里就结束了,我们下期见。。。。。。