(十一)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项目的一些常用功能整合的内容到这里就结束了,我们下期见。。。。。。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/360453.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

项目:博客

1. 运行环境&#xff1a; 主机 主机名 系统 服务 192.168.223.129 Server_Web Linux Web 192.168.48.131 Server-NFS-DNS Linux NFS/DNS 2. 基础配置 配置主机名&#xff0c;静态IP地址 开启防火墙并配置 部分开启SElinux并配置 服务器之间使用同ntp.aliyun.com进行…

eBay测评自养号下单需要满足哪些技术要求?养号优势有哪些?

自养号测评环境搭建系统涉及几个主要环节&#xff1a; 1.系统环境&#xff1a;用于登录和管理多个账号&#xff0c;需具备防关联功能&#xff0c;每个账号使用独立IP&#xff0c;确保完全隔离无关联问题。 2.高质量网络环境&#xff1a;需要国外家庭住宅IP&#xff0c;纯净度…

开发者带你了解山海鲸智慧社区解决方案

作为山海鲸可视化软件的开发者&#xff0c;我们深知在智慧社区建设中&#xff0c;数据可视化对于提升社区管理效率和居民生活品质的重要性。因此在提供人人都能免费使用的产品基础上&#xff0c;特结合山海鲸可视化软件优势打造智慧社区解决方案&#xff0c;本文将为您详细介绍…

sketchup草图大师模型网怎么样?

SketchUp草图大师模型网是一个提供SketchUp模型下载和分享的平台&#xff0c;如建e网等&#xff0c;用户可以在上面找到大量的SU模型&#xff0c;并学习一些SketchUp的使用技巧。该网站模型种类丰富&#xff0c;涵盖了建筑、景观、室内等不同领域&#xff0c;同时也有一些教程&…

6天获邀请函|食品科学老师赴英国Quadram研究所访学交流

C老师拟申报CSC国家公派访问学者项目&#xff0c;因DIY申请无果且申报期临近而求助于我们。依本人要求&#xff0c;我们迅速开展了全方位申请&#xff0c;几天内获得近十个反馈&#xff0c;最终其选择了不需要面试且不收板凳费的英国Quadram研究所&#xff0c;此时距离开展申请…

2024新鲜出炉 Java集合常见面试题总结(上)

2024新鲜出炉 Java集合常见面试题总结(上) 文章目录 2024新鲜出炉 Java集合常见面试题总结(上)集合概述Java 集合概览说说 List, Set, Queue, Map 四者的区别&#xff1f;集合框架底层数据结构总结ListSetQueueMap 如何选用集合?为什么要使用集合&#xff1f; ListArrayList 和…

SOME/IP SD 协议介绍(五)使用SOME/IP-SD宣布非SOME/IP协议的协议。

使用SOME/IP-SD宣布非SOME/IP协议的协议。 除了SOME/IP之外&#xff0c;车辆内部还使用其他通信协议&#xff0c;例如用于网络管理、诊断或闪存更新。这些通信协议可能需要传递服务实例或具有事件组。 对于非SOME/IP协议&#xff0c;应使用特殊的服务ID&#xff0c;并使用配置…

最新盘点!2024年最好用的十大进销存管理系统

深度盘点国内外十大进销存管理系统&#xff1a;简道云进销存、Oracle NetSuite、金蝶精斗云、用友、浪潮云进销存、傻瓜进销存、旺店通、生意专家、QT9、Linnworks。 进销存指的是企业管理过程中采购&#xff08;进&#xff09;——入库&#xff08;存&#xff09;——销售&am…

20240127在ubuntu20.04.6下配置whisper

20240131在ubuntu20.04.6下配置whisper 2024/1/31 15:48 首先你要有一张NVIDIA的显卡&#xff0c;比如我用的PDD拼多多的二手GTX1080显卡。【并且极其可能是矿卡&#xff01;】800&#xffe5; 2、请正确安装好NVIDIA最新的驱动程序和CUDA。可选安装&#xff01; 3、配置whispe…

备战蓝桥杯---数据结构与STL应用(入门3)

我们先来一道题作为过渡&#xff1a; 我们只需枚举n,选出左右第一个小于它高度的坐标即可&#xff0c;于是我们可以用两个方向的优先队列来维护&#xff0c;下面是AC代码&#xff1a; #include<bits/stdc.h> using namespace std; #define int long long int n; struct …

基于ssm和微信小程序的健身房私教预约管理系统

文章目录 项目介绍主要功能截图&#xff1a;部分代码展示设计总结项目获取方式 &#x1f345; 作者主页&#xff1a;超级无敌暴龙战士塔塔开 &#x1f345; 简介&#xff1a;Java领域优质创作者&#x1f3c6;、 简历模板、学习资料、面试题库【关注我&#xff0c;都给你】 &…

Word莫名其妙开启兼容模式将其永久取消的方法

这是因为Word模板文件被意外更改了 找到Word模板文件&#xff0c;目录在C:\Users\15976\AppData\Roaming\Microsoft\Templates 15976替换成你自己的用户名&#xff0c;不确定的就先点进C/Users看一看&#xff0c; AppData是隐藏文件夹&#xff0c;显示隐藏文件夹才能看见&am…

MySQL备份和恢复(二)mysqldump

注意&#xff1a;mysqldump是完全备份 一、mysqldump备份命令 1、 备份数据库 含创建库语句 &#xff08;1&#xff09;备份指定数据库 完全备份一个或多个完整的库&#xff0c; mysqldump -uroot -p[密码] --databases 库名1 [库名2].. >/备份路径/备份文件名.sql#导出…

安泰高压放大器电路设计方案是什么

高压放大器是电子设备中常用的一种放大器类型&#xff0c;用于将低电压信号放大到高电压输出。本文将介绍高压放大器电路设计的基本原理和方案&#xff0c;涵盖关键设计考虑因素以及常用的电路拓扑结构。 一、设计考虑因素 放大倍数&#xff1a;高压放大器的设计首要考虑因素是…

【海贼王编程冒险 - C语言海上篇】自定义类型:结构体,枚举,联合怎样定义?如何使用?

目录 1 -> 结构体的声明 1.1 -> 结构的基础知识 1.2 -> 结构的声明 1.3 -> 特殊的声明 1.4 -> 结构的自引用 1.5 -> 结构体变量的定义与初始化 1.6 -> 结构体内存对齐 1.7 -> 修改默认对齐数 1.8 -> 结构体传参 2 -> 位段 2.1 -> …

山体滑坡在线安全监测预警系统(解决方案)

在近年来&#xff0c;随着全球气候变化的影响&#xff0c;山体滑坡等自然灾害频发&#xff0c;给人们的生命财产安全带来了严重威胁。为了有效预防和减少山体滑坡带来的危害&#xff0c;许多地方开始在山上安装山体滑坡在线安全监测预警系统&#xff08;解决方案&#xff09;。…

代码编写大模型

Code Llama 70B 提供与之前发布的 Code Llama 型号相同的三个版本&#xff1a; CodeLlama - 70B&#xff0c;基础代码模型&#xff1b;CodeLlama - 70B - Python&#xff0c;专门面向 Python 的 70B&#xff1b;Code Llama - 70B - Instruct 70B&#xff0c;它针对理解自然语言…

【gulp+jq+html】添加环境变量,并在js中使用(判断环境,更改api接口域名)+ 附gulpfile.js代码

参考博文&#xff1a; gulp分离环境 gulp中如何配置环境变量 gulp环境变量配置 1、安装cross-env插件 npm install cross-env -d2、package.json更改scripts "scripts": {"clean": "gulp clean","serve:test": "cross-env NODE…

503 Service Temporarily Unavailable nginx 原因和解决办法

前言 HTTP 503 Service Temporarily Unavailable 错误通常表示服务器无法处理请求&#xff0c;可能是由于服务器过载、维护或其他临时性问题导致的。在 Nginx 中&#xff0c;这种错误通常与后端服务的可用性问题相关。以下是可能的原因和解决办法&#xff1a; 正文…

UE4 CustomDepthMobile流程小记

原生UE opaque材质中获取CustomDepth/CustomStencil会报错 在其Compile中调用的函数中没有看到报错逻辑 材质节点的逻辑都没有什么问题&#xff0c;所以看一下报错 在HLSLMaterialTranslator::Translate中 修改之后 mobile流程的不透明材质可以直接获取SceneTexture::customd…
最新文章