Spring Cloud 项目中使用 Swagger

Spring Cloud 项目中使用 Swagger

  • 关于方案的选择
    在 Spring Cloud 项目中使用 Swagger 有以下 4 种方式:

  • 方式一 :在网关处引入 Swagger ,去聚合各个微服务的 Swagger。未来是访问网关的 Swagger 原生界面。

  • 方式二 :在网关处引入 knife4j,去聚合各个微服务的 Swagger。未来是访问网关的 knife4j 的美化版界面。

  • 方式三 :使用 knife4j 去创建一个独立的聚合项目,去聚合各个微服务的 Swagger。未来是访问这个聚合项目的 knife4j 的美化版界面。

  • 方式四 :使用独立的、另外的第三方工具(例如,Apifox),去聚合各个微服务的 Swagger。未来是访问这个第三方工具。

在上述 4 种方案中,我们选择的是方案四,原因在于:

  • 对于方案一方案二而言,本质上是一样的,主要无非就是页面美不美观的问题。knife4j 的页面要强过 swagger 的原生界面的,但和第三方工具比起来,还是远不如第三方插件好看(和功能丰富)。
  • knife4j 对原生 Swagger 有所拓展,提升了便捷性,但是提升有效。如果抛开“页面美观”这个主要优点,其它有关“拓展”层面的优点并没有那么多的“非用不可”。
  • 方案三的 knife4j 的聚合项目虽然能够很方便的集合各个微服务,使用上要方便于网关聚合,但是,你是用它就意味着你的测试请求都绕过了网关,如果你在网管处有代码逻辑,那么这部分代码就“跳”过去了,不利于测试。

所以,从美观、完善各方面综合考虑,我们采用上面的方案四

使用方案四意味着:

  • 我们的项目中只需要引入 swagger 的包,不需要引入 knife4j 的包。
  • 如果我们不需要在网关处看到原生的 swagger 页面,那么网关项目不需要有任何改动。原生的 swagger 页面,那么网关项目不需要有任何改动。

各个微服务的改动

改动一:引包和配置文件
<dependency>  
    <groupId>com.github.xiaoymin</groupId>  
    <artifactId>knife4j-spring-boot-starter</artifactId>  
    <version>3.0.3</version>  
    <!--<version>2.0.9</version>-->  
</dependency>
# knife4j公共配置  
knife4j.enable=true
改动二:新增配置类
@Configuration  
@EnableOpenApi  
@RequiredArgsConstructor  
public class SwaggerConfiguration {  
  
    private final OpenApiExtensionResolver openApiExtensionResolver;  
  
    @Value("${spring.application.name}")  
    private String applicationName;  
  
    @Bean  
    @Order(value = 1)  
    public Docket docDocket() {  
        return new Docket(DocumentationType.OAS_30)  
                .pathMapping("/" + applicationName) // ==> /department-service  
                .enable(true)  
                .apiInfo(groupApiInfo())  
                .select()  
                .apis(RequestHandlerSelectors.withMethodAnnotation(Operation.class))  
                .paths(PathSelectors.any())  
                .build()  
                .extensions(openApiExtensionResolver.buildExtensions("部门微服务"))  
                ;  
    }  
  
    private ApiInfo groupApiInfo() {  
        return new ApiInfoBuilder()  
                .title("Knife4j接口文档")  
                .description("Knife4j接口文档")  
                .termsOfServiceUrl("https://doc.xiaominfo.com/")  
                .version("1.0.0")  
                .build();  
    }
}
关键项说明

上述内容,无论是 pom 引包,还是加配置类,绝大部分内容都是复制粘贴,无需改动的。

但是在配置类中,有一个信息必须注意,它必须和你的 spring-cloud 的配置相关:

.pathMapping("/" + applicationName) 

.pathMapping() 方法的值表示的是:Swagger 对外暴露的测试功能中,在原本的(@RestController)的 URI 之外,额外加上一段什么样的前缀。

为什么会有这样的要求?

未来,无论是在 Apifox 这样的第三方工具中测试,还是在网关处的原生的 Swagger 页面上进行测试,我们的测试请求都是应该发送给网关的,再由网关将请求路由给微服务。

所以,在 Apifox 中,或者是网管处的原生的 Swagger 中,我们发送请求的“前一段”的 IP 和 Port 的组合是网关的 IP 和 Port 。而网关在默认情况下则是根据它所收到的“请求的 URI 中的前一段和微服务的服务名的匹配情况”作为依据来路由请求。

如果,各个微服务的 Swagger 的配置中没有主动的多“加上”一段能路由到自己的 URI 前缀,那么 Swagger 所暴露出来的请求测试功能所产生的拼接出来的 URI 就成了:网关的 IP 和 Port 拼上微服务的 URI,而没有微服务标识那一段。例如:

## 127.0.0.1:10000 是网关地址
http://127.0.0.1:10000/department/delete

但是,从上帝视角看,本应该是:

## 127.0.0.1:10000 是网关地址
http://127.0.0.1:10000/department-service/department/delete

只有这样,Swagger 所暴露出来的测试功能才能正常使用。

所以,这就需要 department-service 自己在它的 Swagger 配置中说明:在自己的 Swagger 暴露的测试功能中,需要在正常的 URI 前面“多”加上 /department-service 前缀,这样才能让 Swagger 暴露的 URI 经过网关后正常路由到自己这里来。

网关处的改动

注意
如果你不指望在网关处看到、访问原生的 Swagger 界面,那么,这一步操作就不是必须的,不用做。

引入 swagger 包
<dependency>  
    <groupId>io.springfox</groupId>  
    <artifactId>springfox-boot-starter</artifactId>  
    <version>3.0.0</version>  
</dependency>
新增配置类
@Primary  
@Configuration  
@EnableOpenApi  
@RequiredArgsConstructor  
public class SwaggerConfig implements SwaggerResourcesProvider {  
  
    private static final String OAS_30_URL = "/v3/api-docs";  
  
    private final RouteLocator routeLocator;  
  
    private final GatewayProperties gatewayProperties;  
  
    /**  
     * 网关应用名称     
     */
    @Value("${spring.application.name}")  
    private String self;  
  
    @Override  
    public List<SwaggerResource> get() {  
        List<SwaggerResource> resources = new ArrayList<>();  
        List<String> routeHosts = new ArrayList<>();  
        routeLocator.getRoutes()  
                .filter(route -> route.getUri().getHost() != null)  
                .filter(route -> Objects.equals(route.getUri().getScheme(), "lb"))  
                // 过滤掉网关自身的服务 uri 中的 host 就是服务 id 
                .filter(route -> !self.equalsIgnoreCase(route.getUri().getHost()))  
                .subscribe(route -> routeHosts.add(route.getUri().getHost()));  
  
        // 记录已经添加过的server,存在同一个应用注册了多个服务在注册中心上  
        Set<String> dealed = new HashSet<>();  
        routeHosts.forEach(instance -> {  
            // 拼接 url ,目标 swagger 的 url  
            String url = "/" + instance.toLowerCase() + OAS_30_URL;  
            System.out.println("url: " + url);  
            if (!dealed.contains(url)) {  
                dealed.add(url);  
                SwaggerResource swaggerResource = new SwaggerResource();  
                swaggerResource.setUrl(url);  
                swaggerResource.setName(instance);  
                //swaggerResource.setSwaggerVersion("3.0.3");  
                resources.add(swaggerResource);  
            }  
        });  
        return resources;  
    }  
  
}

Apifox 引入

image.png

image.png

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

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

相关文章

软件设计师笔记2

文章目录 软考知识点总结1. 计算机组成原理网络与信息安全数据结构与算法AOE网 编译原理操作系统软件设计软件测试数据库计算机软件产权其它 软考知识点总结 1. 计算机组成原理 cpu控制器&#xff0c;专门产生指令操作&#xff0c;送到计算机各个部位执行处理 DMA&#xff08…

ISCC2024个人挑战赛WP-WEB

&#xff08;非官方解&#xff0c;以下内容均互联网收集的信息和个人思路&#xff0c;仅供学习参考&#xff09; 还没想好名字的塔防游戏 GET /world.js HTTP/1.1 Host: 101.200.138.180:17345 Accept: text/html,application/xhtmlxml,application/xml;q0.9,image/avif,i…

LeetCode题练习与总结:二叉树的层序遍历Ⅱ--107

一、题目描述 给你二叉树的根节点 root &#xff0c;返回其节点值 自底向上的层序遍历 。 &#xff08;即按从叶子节点所在层到根节点所在的层&#xff0c;逐层从左向右遍历&#xff09; 示例 1&#xff1a; 输入&#xff1a;root [3,9,20,null,null,15,7] 输出&#xff1a;[…

嵌入式进阶——LED呼吸灯(PWM)

&#x1f3ac; 秋野酱&#xff1a;《个人主页》 &#x1f525; 个人专栏:《Java专栏》《Python专栏》 ⛺️心若有所向往,何惧道阻且长 文章目录 PWM基础概念STC8H芯片PWMA应用PWM配置详解占空比 PWM基础概念 PWM全称是脉宽调制&#xff08;Pulse Width Modulation&#xff09…

C++笔试强训day33

目录 1.跳台阶扩展问题 2.包含不超过两种字符的最长子串 3.字符串的排列 1.跳台阶扩展问题 链接https://www.nowcoder.com/practice/953b74ca5c4d44bb91f39ac4ddea0fee?tpId230&tqId39750&ru/exam/oj 我是用动态规划解决的&#xff1a; #include <iostream>…

一文读懂:http免费升级https

背景&#xff1a; 随着现在全民网络安全意识的日益提升&#xff0c;各个网站需要实现的https数量也随之提升&#xff0c;那么如何将原本网站的http访问方式升级为https呢&#xff1f; 该内容为如何免费将网站的http访问升级为https访问 论https的加密逻辑&#xff1a; 步骤 …

【数据结构(邓俊辉)学习笔记】图01——图的表示与实现

文章目录 1. 概述1.1 邻接 关联1.2 无向 有向1.3 路径 环路 2. 邻接矩阵2.1 接口2.2 邻接矩阵 关联矩阵2.3 实例2.4 顶点和边2.5 邻接矩阵2.6 顶点静态操作2.7 边操作2.7 顶点动态操作2.8 综合评价 1. 概述 1.1 邻接 关联 相对于此前的线性以及半线性结构&#xff0c;图…

RAG概述(二):Advanced RAG 高级RAG

目录 概述 Advanced RAG Pre-Retrieval预检索 优化索引 增强数据粒度 粗粒度 细粒度 展开说说 优化索引 Chunk策略 Small2Big方法 元数据 引入假设性问题 对齐优化 混合检索 查询优化 查询扩展 查询转换 Post-Retrieval后检索 参考 概述 Native RAG&#…

Python并发编程学习记录

1、初识并发编程 1.1、串行&#xff0c;并行&#xff0c;并发 串行(serial)&#xff1a;一个cpu上按顺序完成多个任务&#xff1b; 并行(parallelism)&#xff1a;任务数小于或等于cup核数&#xff0c;多个任务是同时执行的&#xff1b; 并发(concurrency)&#xff1a;一个…

Linux之Nginx

1、Nginx 1.1、什么是Nginx Nginx最初由Igor Sysoev开发&#xff0c;最早在2004年公开发布。它被设计为一个轻量级、高性能的服务器&#xff0c;能够处理大量并发连接而不消耗过多的系统资源。Nginx的架构采用了事件驱动的方式&#xff0c;能够高效地处理请求。它的模块化设计使…

Redis 的持久化(真的好细)

前言 Redis 是一个内存数据库&#xff0c;把数据存储在内存中&#xff0c;而内存中的数据是不持久的&#xff0c;要想数据持久就得将数据存储到硬盘中&#xff0c;而 Redis 相比于 Mysql 这样的关系型数据库最大的优势就在于将数据存储在内存中从而效率更高&#xff0c;速度更快…

大数据智慧消防解决方案(24页PPT)

方案介绍&#xff1a; 大数据智慧消防解决方案是提升消防安全管理水平、保障人民群众生命财产安全的重要手段。通过集成物联网、云计算、大数据、人工智能等先进技术&#xff0c;构建集监测、预警、指挥、救援于一体的智慧消防系统&#xff0c;将为消防安全事业注入新的活力。…

单日收益1000+看了就会的项目,最新灵异短视频项目,简单好上手可放大操作

各位好友&#xff0c;佳哥在此与大伙儿聊聊一项神秘莫测的短视频项目。你或许会想&#xff0c;“又是一个视频创作项目&#xff1f;” 但别急&#xff0c;这个项目与众不同&#xff0c;日入千元不再是梦&#xff0c;而且它的易用性让人惊喜&#xff0c;无论你是初学者还是资深玩…

数据结构·一篇搞定队列!

hello&#xff0c;大家好啊&#xff0c;肖恩又拖更了&#xff0c;你们听我狡辩&#xff0c;前段时间有期中考试&#xff0c;so我就没什么时间写这个&#xff0c;在这给大家道个歉&#x1f62d;&#x1f62d;&#x1f62d; 我后面一定尽力不拖更 那么接下来&#xff0c;我们来看…

数字化转型必备:营销策划流程图,打造你的数字市场地图

制作营销策划流程图是一个系统化的过程&#xff0c;它可以帮助你清晰地规划和展示营销活动的各个阶段。 以下是制作营销策划流程图的步骤&#xff1a; 1.确定营销目标&#xff1a; 明确你的营销活动旨在实现的具体目标&#xff0c;比如提升品牌知名度、增加销售额、吸引新客…

【CCIE | 网络模拟器】部署 EVE-NG

目录 1. 环境准备2. 下载 EVE-NG 镜像3. 安装 EVE-NG 虚拟机3.1 创建 eve-ng 虚拟机3.2 选择存储3.3 定义虚拟机计算资源&#xff08;1&#xff09;开启CPU虚拟化功能&#xff08;2&#xff09;精简置备磁盘 3.4 检查虚拟机设置 4. 安装系统4.1 选择系统语言4.2 选择系统键盘类…

2024.05.25 第 131 场双周赛

Leetcode 第 131 场双周赛 求出出现两次数字的 XOR 值 [Leetcode 求出出现两次数字的 XOR 值](https://leetcode.cn/problems/find-the-xor-of-numbers-which-appear-twice/description/] 给你一个数组 nums &#xff0c;数组中的数字 要么 出现一次&#xff0c;要么 出现两次…

自从有了可观测性,传统运维如何进行提升?

在 201x 年&#xff0c;随着容器技术的出现&#xff0c;容器的部署方式逐渐被各大互联网公司采用&#xff0c;相比物理机/虚拟机&#xff0c;容器的好处是环境隔离、轻量、快速。 但是管理容器是一件复杂的事情&#xff0c;后来出现了 Kubernetes&#xff0c;成为了事实上的容…

数据结构(五)树与二叉树

2024年5月26日一稿(王道P142) 基本概念 术语 性质 二叉树 5.2.2 二叉树存储结构

MySQL|主从复制配置

我使用的是两个云服务器&#xff0c;如果读者使用的是虚拟机和本机&#xff0c;配置会简单很多。 关于云服务器安全组设置、防火墙端口等问题请参考文章&#xff1a; 使用华为云服务器进行项目部署&#xff08;云服务器、防火墙配置&#xff09; 条件&#xff1a;master 和 s…