微服务下网关聚合Swagger文档、starter统一配置Swagger
一、starter实现统一配置微服务文档
- 把Swagger配置中的公共部分抽取出来
- Swagger与SpringBoot整合中,可能会由于版本问题出现各种问题
1、制作starter
参考:
- 【SpringBoot】自定义启动器 Starter【保姆级教程】
- 用starter实现Oauth2中资源服务的统一配置
- 用starter实现api接口的加密与日志功能
- 用spring-boot-starter实现事务的统一配置
1> 总体结构图

2> 外部引用模块
tuwer-swagger-spring-boot-starter
- pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"><modelVersion>4.0.0</modelVersion><groupId>com.tuwer</groupId><artifactId>tuwer-swagger-spring-boot-starter</artifactId><version>1.0-SNAPSHOT</version><description>swagger配置starter</description><properties><maven.compiler.source>8</maven.compiler.source><maven.compiler.target>8</maven.compiler.target></properties><dependencies><!-- 自动配置模块 --><dependency><groupId>com.tuwer</groupId><artifactId>tuwer-swagger-spring-boot-starter-autoconfigure</artifactId><version>1.0-SNAPSHOT</version></dependency></dependencies>
</project>
3> 自动配置模块
- pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"><parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-parent</artifactId><version>2.6.7</version></parent><modelVersion>4.0.0</modelVersion><groupId>com.tuwer</groupId><artifactId>tuwer-swagger-spring-boot-starter-autoconfigure</artifactId><version>1.0-SNAPSHOT</version><description>swagger自动配置模块</description><properties><maven.compiler.source>8</maven.compiler.source><maven.compiler.target>8</maven.compiler.target></properties><dependencies><!-- 基础启动器 --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter</artifactId></dependency><!-- web --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><!-- Swagger --><dependency><groupId>io.springfox</groupId><artifactId>springfox-boot-starter</artifactId><version>3.0.0</version></dependency><!-- actuator完善监控信息 --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-actuator</artifactId></dependency><!-- lombok --><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><version>1.18.22</version></dependency></dependencies>
</project>
- 自动配置类
不要加
@EnableWebMvc
package com.tuwer.config;import org.springframework.boot.actuate.autoconfigure.endpoint.web.CorsEndpointProperties;
import org.springframework.boot.actuate.autoconfigure.endpoint.web.WebEndpointProperties;
import org.springframework.boot.actuate.autoconfigure.web.server.ManagementPortType;
import org.springframework.boot.actuate.endpoint.ExposableEndpoint;
import org.springframework.boot.actuate.endpoint.web.*;
import org.springframework.boot.actuate.endpoint.web.annotation.ControllerEndpointsSupplier;
import org.springframework.boot.actuate.endpoint.web.annotation.ServletEndpointsSupplier;
import org.springframework.boot.actuate.endpoint.web.servlet.WebMvcEndpointHandlerMapping;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.env.Environment;
import org.springframework.util.StringUtils;
import springfox.documentation.builders.RequestHandlerSelectors;
import springfox.documentation.service.ApiInfo;
import springfox.documentation.service.Contact;
import springfox.documentation.spi.DocumentationType;
import springfox.documentation.spring.web.plugins.Docket;import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;/*** @author 土味儿* Date 2023/4/21* @version 1.0* 这里不要加EnableWebMvc注解;否则响应数据会出现乱码*/
@Configuration
//@EnableWebMvc
@EnableConfigurationProperties(SwaggerProperty.class)
public class SwaggerConfig {@ResourceSwaggerProperty swaggerProperty;/*** 配置Swagger具体参数** @return*/@Beanpublic Docket docket(Environment environment) {// 允许启用Swagger的环境//Profiles profile = Profiles.of("dev","test");// 判断当前环境与指定环境是否一致//boolean b = environment.acceptsProfiles(profile);//return new Docket(DocumentationType.OAS_30)return new Docket(DocumentationType.SWAGGER_2)//.apiInfo(apiInfo("tuwer", "搜索服务", "v3.0")).apiInfo(apiInfo(swaggerProperty.getAuthor(), swaggerProperty.getTitle(), swaggerProperty.getVersion()))// 根据当前环境判断是否启用Swagger//.enable(b)//.enable(true)//.groupName("A")// 通过.select()方法,去配置扫描接口,RequestHandlerSelectors配置如何扫描接口.select()// 只扫描特定包下的接口.apis(RequestHandlerSelectors.basePackage(swaggerProperty.getBasePackage()))//.apis(RequestHandlerSelectors.any())//.apis(RequestHandlerSelectors.none())//.apis(RequestHandlerSelectors.withClassAnnotation(RestController.class))//.apis(RequestHandlerSelectors.withMethodAnnotation(GetMapping.class))//.paths(PathSelectors.).build();}/*** 自定义API文档信息** @return*/private ApiInfo apiInfo(String author, String title, String version) {// 作者信息Contact contact = new Contact(author, "", "");return new ApiInfo(title + " API 文档","",version,"",contact,"","",new ArrayList());}/*** 增加如下配置可解决Spring Boot 2.6.x 与 Swagger 3.0.0 不兼容问题* ------------------------------------------* 还需要在yml中作如下配置* mvc:* pathmatch:* matching-strategy: ant_path_matcher**/@Beanpublic WebMvcEndpointHandlerMapping webEndpointServletHandlerMapping(WebEndpointsSupplier webEndpointsSupplier,ServletEndpointsSupplier servletEndpointsSupplier,ControllerEndpointsSupplier controllerEndpointsSupplier,EndpointMediaTypes endpointMediaTypes,CorsEndpointProperties corsProperties,WebEndpointProperties webEndpointProperties,Environment environment) {List<ExposableEndpoint<?>> allEndpoints = new ArrayList();Collection<ExposableWebEndpoint> webEndpoints = webEndpointsSupplier.getEndpoints();allEndpoints.addAll(webEndpoints);allEndpoints.addAll(servletEndpointsSupplier.getEndpoints());allEndpoints.addAll(controllerEndpointsSupplier.getEndpoints());String basePath = webEndpointProperties.getBasePath();EndpointMapping endpointMapping = new EndpointMapping(basePath);boolean shouldRegisterLinksMapping = this.shouldRegisterLinksMapping(webEndpointProperties, environment, basePath);return new WebMvcEndpointHandlerMapping(endpointMapping, webEndpoints, endpointMediaTypes, corsProperties.toCorsConfiguration(), new EndpointLinksResolver(allEndpoints, basePath), shouldRegisterLinksMapping, null);}private boolean shouldRegisterLinksMapping(WebEndpointProperties webEndpointProperties, Environment environment, String basePath) {return webEndpointProperties.getDiscovery().isEnabled() && (StringUtils.hasText(basePath) || ManagementPortType.get(environment).equals(ManagementPortType.DIFFERENT));}}
- 配置属性类
package com.tuwer.config;import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;/*** <p>配置属性类</p>** @author 土味儿* @version 1.0* @Date 2023/4/22*/
@Data
@ConfigurationProperties(prefix = "tuwer-swagger")
public class SwaggerProperty {String author;String title;String version;String basePackage;
}
2、微服务使用starter
1> 注入依赖
需要使用swagger的服务注入
<!-- Swagger -->
<dependency><groupId>com.tuwer</groupId><artifactId>tuwer-swagger-spring-boot-starter</artifactId><version>1.0-SNAPSHOT</version>
</dependency>
2> 添加配置
spring:mvc:pathmatch:# swagger3.0需要:ant_path_matcher# springboot2.6后默认为:path_pattern_parsermatching-strategy: ant_path_matcher# swagger配置
tuwer-swagger:author: 作者title: 服务名称version: 版本base-package: 基础包
3> 接口中添加API文档信息
API接口中添加
// 示例
@RestController
@Api(tags = "接口类描述")
public class TestApi {@PostMapping("/...")@ApiOperation("接口方法描述")public String test(@ApiParam("参数描述")@RequestParam("id") Long id) {// ...}
}
至此,用starter实现微服务的swagger配置完成!
二、网关聚合文档
使用
spring-cloud-gateway网关把各个微服务的文档聚合起来,通过网关统一访问。参考:聚合微服务中的 Swagger API 文档
1、注入依赖
在网关服务中加入Swagger依赖
更加细致的设计思路:(网上有介绍)微服务中不需要Swagger的ui包,只要能生成api的json数据包,供网关抓取就可以。同时网关中也不用自已成生api的json数据包,也可以去掉一些相关的依赖包。
<!-- Swagger -->
<dependency><groupId>io.springfox</groupId><artifactId>springfox-boot-starter</artifactId><version>3.0.0</version>
</dependency>
2、配置网关
不是所有的服务都通过网关转发。有些内部服务可以通过docker的内部网络直接访问,可以单独配置这类内部服务的API文档。
spring:# 配置 Spring Cloud 相关属性cloud:# 配置 Spring Cloud Gateway 相关属性gateway:# 配置网关发现机制discovery:# 配置处理机制locator:enabled: false# 开启服务名称小写转换(默认为false)lower-case-service-id: true# 路由配置routes:# 正常服务1- id: server-1uri: 转发地址predicates:- Path=/server_1/**- Method=GET,POSTfilters:- name: StripPrefixargs:# 过滤掉前1节parts: 1# 正常服务2- id: server-2uri: 转发地址predicates:- Path=/server_2/**- Method=GET,POSTfilters:- name: StripPrefixargs:# 过滤掉前1节parts: 1# swagger文档1- id: swagger-docs-1uri: 转发地址predicates:- Path=/swagger_1/**- Method=GET,POSTfilters:- name: StripPrefixargs:# 过滤掉前1节parts: 1# swagger文档2- id: swagger-docs-2uri: 转发地址predicates:- Path=/swagger_2/**- Method=GET,POSTfilters:- name: StripPrefixargs:# 过滤掉前1节parts: 1
3、Swagger资源抓取类
从网关配置中过滤出Swagger的API文档配置信息
package com.tuwer.config;import lombok.AllArgsConstructor;
import org.springframework.cloud.gateway.config.GatewayProperties;
import org.springframework.cloud.gateway.route.RouteLocator;
import org.springframework.cloud.gateway.support.NameUtils;
import org.springframework.context.annotation.Primary;
import org.springframework.stereotype.Component;
import springfox.documentation.swagger.web.SwaggerResource;
import springfox.documentation.swagger.web.SwaggerResourcesProvider;import java.util.ArrayList;
import java.util.List;
import java.util.Locale;
import java.util.Objects;/*** <p>Swagger资源类</p>** @author 土味儿* @version 1.0* @Date 2023/4/22*/
@Component
@Primary
@AllArgsConstructor
@SuppressWarnings("all")
public class SwaggerResourceConfig implements SwaggerResourcesProvider {private final RouteLocator routeLocator;private final GatewayProperties gatewayProperties;@Overridepublic List<SwaggerResource> get() {List<SwaggerResource> resources = new ArrayList<>();List<String> routes = new ArrayList<>();// 获取所有swagger文档路由的IDrouteLocator.getRoutes().subscribe(route -> {String routeId = route.getId().toLowerCase(Locale.ROOT);// swagger文档的路由ID中包含有:swagger-docsif (routeId.contains("swagger-docs")) {routes.add(route.getId());}});//过滤出配置文件中定义的路由->过滤出Path Route Predicate->根据路径拼接成api-docs路径->生成SwaggerResourcegatewayProperties.getRoutes().stream().filter(routeDefinition -> routes.contains(routeDefinition.getId())).forEach(route -> {route.getPredicates().stream().filter(predicateDefinition -> ("Path").equalsIgnoreCase(predicateDefinition.getName())).forEach(predicateDefinition ->resources.add(swaggerResource(route.getId(),predicateDefinition.getArgs().get(NameUtils.GENERATED_NAME_PREFIX + "0")// 把路径中后面的 ** 替换成文档地址:v2/api-docs.replace("**", "v2/api-docs"))));});return resources;}private SwaggerResource swaggerResource(String name, String location) {//log.info("name:{},location:{}", name, location);SwaggerResource swaggerResource = new SwaggerResource();swaggerResource.setName(SwaggerModel.getByName(name).cnName);swaggerResource.setLocation(location);swaggerResource.setSwaggerVersion("2.0");return swaggerResource;}/*** 枚举类:中英文映射*/enum SwaggerModel {DEFAULT("default", "默认"),S_1("swagger-docs-1", "文档1"),S_2("swagger-docs-2", "文档2");private String name;private String cnName;SwaggerModel(String name, String cnName) {this.name = name;this.cnName = cnName;}public static SwaggerModel getByName(String name) {for (SwaggerModel m : SwaggerModel.values()) {if (Objects.equals(m.name, name)) {//if(m.code == code){return m;}}return DEFAULT;}}
}

相关文章:
微服务下网关聚合Swagger文档、starter统一配置Swagger
一、starter实现统一配置微服务文档 把Swagger配置中的公共部分抽取出来Swagger与SpringBoot整合中,可能会由于版本问题出现各种问题 1、制作starter 参考: 【SpringBoot】自定义启动器 Starter【保姆级教程】用starter实现Oauth2中资源服务的统一配置用…...
剑指 Offer第二版:机器人的运动范围、正则表达式匹配、表示数值的字符串
剑指 Offer第二版 13. 机器人的运动范围19. 正则表达式匹配20. 表示数值的字符串 13. 机器人的运动范围 题目:地上有一个m行n列的方格,从坐标 [0,0] 到坐标 [m-1,n-1] 。一个机器人从坐标 [0, 0] 的格子开始移动,它每次可以向左、右、上、下移…...
Delaunay三角网生成算法
目录 一、分而治之算法二、三角网生长算法三、逐点插入算法四、约束Delaunay三角网1、方法一1、原始点云2、构网结果 1、方法二1、原始点云2、普通Delaunay3、约束Delaunay Delaunay三角剖分分为直接三角剖分和间接三角剖分。间接三角剖分首先计算为Voronoi图,然后由Voronoi图产…...
hashcode是什么?有什么作用?
文章目录 (1)hashcode()方法的作用(2)equals和hashcode的关系(3)百度百科(4)小白解释 Java中Object有一个方法: public native int hashcode(); (1࿰…...
【人体姿态估计】(一)原理介绍
【人体姿态估计】(一)原理介绍 一、背景 人体姿态估计本质上是一个关键点检测的项目; 关键点检测在生活中的应用十分广泛,包括人脸识别、手势识别,而人体姿态估计则是对身体的关键点进行检测; 本文将介…...
一种新的流:为 Java 加入生成器(Generator)特性
作者:文镭(依来) 前言 这篇文章不是工具推荐,也不是应用案例分享。其主题思想,是介绍一种全新的设计模式。它既拥有抽象的数学美感,仅仅从一个简单接口出发,就能推演出庞大的特性集合,引出许多全新概念。…...
《数据结构C++版》实验一:线性表的顺序存储结构
实验目的 1、实现线性表的顺序存储结构 2、熟悉C++程序的基本结构,掌握程序中的头文件、实现文件和主文件之间的相互关系及各自的作用 3、熟悉顺序表的基本操作方式,掌握顺序表相关操作的具体实现 实验内容 对顺序存储的线性表进行一些基本操作。主要包括: (1)插入:操作…...
ChatGPT的开源平替,终于来了!
最近这段时间,一个号称全球最大ChatGPT开源平替项目Open Assistant引起了大家的注意。 这不最近还登上了GitHub的Trending热榜。 https://github.com/LAION-AI/Open-Assistant 根据官方的介绍,Open Assistant也是一个对话式的大型语言模型项目ÿ…...
Redis基础
Redis6 1. NoSQL数据库简介 1.1 技术发展 技术的分类 1、解决功能性的问题:Java、Jsp、RDBMS、Tomcat、HTML、Linux、JDBC、SVN。 2、解决扩展性的问题:Struts、Spring、SpringMVC、Hibernate、Mybatis。 3、解决性能的问题:NoSQL、Jav…...
为什么重视安全的公司都在用SSL安全证书?
我们今天来讲一讲为什么重视安全的公司都在用SSL证书 SSL证书是什么? SSL安全证书是由权威认证机构颁发的,是CA机构将公钥和相关信息写入一个文件,CA机构用他们的私钥对我们的公钥和相关信息进行签名后,将签名信息也写入这个文件…...
嵌入式QT (使用 Qt Designer 开发)
一、使用 UI 设计器开发程序 1.1、 在 UI 文件添加一个按钮 1.2、在 UI 文件里连接信号与槽 所谓信号即是一个对象发出的信号,槽即是当这个对象发出这个信号时,对应连接的槽就发被执行或者触发。 UI 设计器里信号与槽的连接方法一: 在主窗…...
每日一个小技巧:今天告诉你拍照识别文字的软件有哪些
在现代社会里,手机已经成为了人们生活中必不可少的工具。它的功能众多,比如通讯、上网、拍照以及导航等,为我们的生活带来了许多便利。除此之外,手机还能帮助我们解决一些实际的问题,例如,当你需要识别图片…...
多版本VersionARXDBG
提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 文章目录 前言一、一级标题二级标题三级标题四级标题五级标题六级标题总结前言 提示:这里可以添加本文要记录的大概内容: VersionARXDBG,多版本,2023.4.22-4.23两天时间,分别研究了在多版本编译ARXDB…...
# 生成器
生成器 生成器是什么? 生成器(generator)是一种用来生成数据的对象。它们是普通函数的一种特殊形式,可以用来控制数据的生成过程。 生成器有什么优势? 使用生成器的优势在于它们可以在生成数据的同时控制数据的生成过程…...
Netty 源码解析(上)
序 Netty的影响力以及使用场景就不用多说了, 去年10月份后,就着手研究Netty源码,之前研究过Spring源码,MyBatis源码,java.util.concurrent源码,tomcat源码,发现一个特点,之前的源码都…...
Vue 消息订阅与发布
消息订阅与发布,也可以实现任意组件之间的通信。 订阅者:就相当于是我们,用于接收数据。 发布者:就相当于是媒体,用于传递数据。 安装消息订阅与发布插件: 在原生 JS 中 不太容易实现消息订阅与发布&…...
如何在你的云服务器/云主机上更新并使用最新版本的python(python3.11)
更新并使用最新版本的python3.11 第一步,登录云服务器,并更新系统包 打开您的终端(Terminal)或使用任意SSH客户端,输入如下命令来登录云主机: ssh 用户名IP地址 在输入密码后,您将成功登录到云…...
python学习——【第八弹】
前言 上篇文章 python学习——【第七弹】学习了python中的可变序列集合,自此python中的序列的学习就完成啦,这篇文章开始学习python中的函数。 函数 在学习其他编程语言的时候我们就了解过函数:函数就是执行特定任何以完成特定功能的一段代…...
铁路应答器传输系统介绍
应答器传输系统 应答器传输系统是安全点式信息传输系统,通过应答器实现地面设备向车载设备传输信息。 应答器可根据应用需求向车载设备传输固定的(通过无源应答器)或可变的(通过有源应答器)上行链路数据。 当天线单…...
Baumer工业相机堡盟工业相机如何通过BGAPI SDK直接实现Mono16位深度的图像保存(C#)
Baumer工业相机堡盟工业相机如何通过BGAPI SDK直接实现Mono16位深度的图像保存(C#) Baumer工业相机Baumer工业相机保存位深度12/16位图像的技术背景代码案例分享1:引用合适的类文件2:通过BGAPI SDK直接保存Mono12/16图像3…...
MPNet:旋转机械轻量化故障诊断模型详解python代码复现
目录 一、问题背景与挑战 二、MPNet核心架构 2.1 多分支特征融合模块(MBFM) 2.2 残差注意力金字塔模块(RAPM) 2.2.1 空间金字塔注意力(SPA) 2.2.2 金字塔残差块(PRBlock) 2.3 分类器设计 三、关键技术突破 3.1 多尺度特征融合 3.2 轻量化设计策略 3.3 抗噪声…...
ubuntu搭建nfs服务centos挂载访问
在Ubuntu上设置NFS服务器 在Ubuntu上,你可以使用apt包管理器来安装NFS服务器。打开终端并运行: sudo apt update sudo apt install nfs-kernel-server创建共享目录 创建一个目录用于共享,例如/shared: sudo mkdir /shared sud…...
【Oracle APEX开发小技巧12】
有如下需求: 有一个问题反馈页面,要实现在apex页面展示能直观看到反馈时间超过7天未处理的数据,方便管理员及时处理反馈。 我的方法:直接将逻辑写在SQL中,这样可以直接在页面展示 完整代码: SELECTSF.FE…...
大语言模型如何处理长文本?常用文本分割技术详解
为什么需要文本分割? 引言:为什么需要文本分割?一、基础文本分割方法1. 按段落分割(Paragraph Splitting)2. 按句子分割(Sentence Splitting)二、高级文本分割策略3. 重叠分割(Sliding Window)4. 递归分割(Recursive Splitting)三、生产级工具推荐5. 使用LangChain的…...
【快手拥抱开源】通过快手团队开源的 KwaiCoder-AutoThink-preview 解锁大语言模型的潜力
引言: 在人工智能快速发展的浪潮中,快手Kwaipilot团队推出的 KwaiCoder-AutoThink-preview 具有里程碑意义——这是首个公开的AutoThink大语言模型(LLM)。该模型代表着该领域的重大突破,通过独特方式融合思考与非思考…...
在Ubuntu中设置开机自动运行(sudo)指令的指南
在Ubuntu系统中,有时需要在系统启动时自动执行某些命令,特别是需要 sudo权限的指令。为了实现这一功能,可以使用多种方法,包括编写Systemd服务、配置 rc.local文件或使用 cron任务计划。本文将详细介绍这些方法,并提供…...
精益数据分析(97/126):邮件营销与用户参与度的关键指标优化指南
精益数据分析(97/126):邮件营销与用户参与度的关键指标优化指南 在数字化营销时代,邮件列表效度、用户参与度和网站性能等指标往往决定着创业公司的增长成败。今天,我们将深入解析邮件打开率、网站可用性、页面参与时…...
DeepSeek 技术赋能无人农场协同作业:用 AI 重构农田管理 “神经网”
目录 一、引言二、DeepSeek 技术大揭秘2.1 核心架构解析2.2 关键技术剖析 三、智能农业无人农场协同作业现状3.1 发展现状概述3.2 协同作业模式介绍 四、DeepSeek 的 “农场奇妙游”4.1 数据处理与分析4.2 作物生长监测与预测4.3 病虫害防治4.4 农机协同作业调度 五、实际案例大…...
力扣-35.搜索插入位置
题目描述 给定一个排序数组和一个目标值,在数组中找到目标值,并返回其索引。如果目标值不存在于数组中,返回它将会被按顺序插入的位置。 请必须使用时间复杂度为 O(log n) 的算法。 class Solution {public int searchInsert(int[] nums, …...
算法笔记2
1.字符串拼接最好用StringBuilder,不用String 2.创建List<>类型的数组并创建内存 List arr[] new ArrayList[26]; Arrays.setAll(arr, i -> new ArrayList<>()); 3.去掉首尾空格...
