(十一)springboot实战——springboot3下关于WebFlux项目的一些常用功能整合

前言

本节内容主要是对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项目的一些常用功能整合的内容到这里就结束了,我们下期见。。。。。。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

厉害哥哥吖

您的支持是我创作下去的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值