spring boot 3.3.4 网关(gateway) 集成knife4j 4.4.0

spring boot版本 3.3.4,jdk 22, springcloud 2023.0.3

官方参考链接 

Spring Cloud Gateway网关聚合 | Knife4j (xiaominfo.com)

springboot版本信息

<properties> 
    <java.version>22</java.version> 
    <spring-cloud.version>2023.0.3</spring-cloud.version> 
</properties>

<parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>3.3.4</version>
    <relativePath/>
</parent>

一、网关集成 knife4j 4.4.0

<dependency>  这是网关的maven坐标,它不用spring boot自带的tomcat
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-gateway</artifactId>
</dependency>

<dependency>
    <groupId>com.github.xiaoymin</groupId>
    <artifactId>knife4j-gateway-spring-boot-starter</artifactId>
    <version>4.4.0</version>
</dependency>

<dependency>
    <groupId>com.github.xiaoymin</groupId>
    <artifactId>knife4j-openapi3-jakarta-spring-boot-starter</artifactId>
    <version>4.4.0</version>
</dependency>

网关的核心配置

server:
  port: 9101
  servlet:
    context-path: /
spring:
  main:
    web-application-type: reactive #不使用tomcat的配置,与gateway无关
  application:
    name: GatewayApp
  cloud:
    gateway:
      #保证通过网关能访问子服务的配置 这个与gateway无关,主要是fegin调用使用
      routes:
        - id: ServiceApp9100 #你的子服务
          uri: http://localhost:9100
          predicates:
          - Path=/service/**   # service子服务的context-path值
        - id: PortalApp9099  #你的子服务
          uri: http://localhost:9099
          predicates:
          - Path=/protal/**
  
eureka: # 配置确认通过网关可以从eureka调用到子服务
  instance:
    lease-expiration-duration-in-seconds: 30
    lease-renewal-interval-in-seconds: 10
    hostname: localhost     #服务主机名称
    prefer-ip-address: true #是否优先使用ip来作为主机名
  client:
    register-with-eureka: true #注册到Eureka的注册中心
    fetch-registry: true #获取注册实例列表
    enabled: true # 启用eureka客户端
    registry-fetch-interval-seconds: 30 #定义去eureka服务端获取服务列表的时间间隔
    healthcheck:
      enabled: true
    service-url:
      defaultZone: http://localhost:9098/eureka/ #eureka服务的地址
 
knife4j:          #这里是重点
  gateway:
    # 开起网关聚合文档
    enabled: true
    # 网关前缀(如nginx配置的代理前缀) 默认:/
    api-path-prefix: /
    # 使用的UI版本(v2或者v3) 默认: v3
    version: v3
    # 指定服务发现的模式聚合微服务文档,并且是默认 default 分组
    strategy: discover
    # 服务发现
    discover:
      # OpenAPI 3.0 规范
      version: openapi3
      # 开启服务发现 默认:true
      enabled: true
      # 默认排序 默认:0
      default-order: 0
      # 排除的服务名 默认:为空(建议排除网关服务)
      excluded-services: ${spring.application.name}
    routes:
      # 子服务分组名称
      #子服务的服务名跟你的子服务名字一样就行 一般用servlet.context-path的值
      - name: service
        #这里很重要 必须有【service】,否则访问的是ip:port/v3/apidocs,报404
        #官网在这里根本没有解释,估计官网写文档的认为开发都是高手,没有多余的交代
        #service漏写很痛苦,各种尝试,各种jar包替换,没有过多的交代,导致开发者填坑
        url: 'service/v3/api-docs'
        # context-path
        context-path: '/service'
        # 服务名
        service-name: service
        # 排序
        order: 1

上面的配置完,就能启动网关服务访问,前提是子服务也得集成结束(参见下文 “二、子服务集成”),要不然会报错

http://127.0.0.1:9101/doc.html  网关服务的访问地址/doc.html

高版本就是引入maven坐标,添加配置,启动项目就行,不用做任何配置类操作。

补充一点关于上面的访问链接 浏览器控制台404问题

源代码中 这个访问路径

knife4j:
  gateway:
    enabled: true   #配置文件有这个就行

新增了两个maven坐标,原因是网关gateway排除了springboot自带的Tomcat包

<dependency>
    <groupId>javax.servlet</groupId>
    <artifactId>javax.servlet-api</artifactId>
    <version>4.0.1</version>
    <scope>provided</scope>
</dependency>
<dependency>
    <groupId>org.apache.tomcat.embed</groupId>
    <artifactId>tomcat-embed-core</artifactId>
</dependency>

网关增加的配置类,目的是在网关访问时处理一下访问的路径,主要原因是它可能出现了

http://ip:port//xxx     /这里是空/     这种情况导致404,启动成功能正常访问,可以将这个配置类伤处试试,莫名其妙的也正常了。

import jakarta.servlet.http.HttpServletRequest;
import org.apache.commons.lang3.RegExUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.logging.log4j.util.Strings;
import org.springdoc.core.properties.SpringDocConfigProperties;
import org.springdoc.core.properties.SwaggerUiConfigParameters;
import org.springdoc.core.properties.SwaggerUiConfigProperties;
import org.springdoc.core.properties.SwaggerUiOAuthProperties;
import org.springdoc.core.providers.ObjectMapperProvider;
import org.springdoc.webmvc.core.configuration.SpringDocWebMvcConfiguration;
import org.springdoc.webmvc.ui.SwaggerIndexPageTransformer;
import org.springdoc.webmvc.ui.SwaggerWelcomeCommon;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.io.Resource;
import org.springframework.web.servlet.resource.ResourceTransformerChain;

import java.io.IOException;
import java.util.Optional;

@Configuration
@ConditionalOnClass(SpringDocWebMvcConfiguration.class)
public class SwaggerConfiguration {

    /**
     * 重写swagger地址,通过浏览器访问/swagger-ui/index.html时,html页面会请求/v3/api-docs和/v3/api-docs/swagger-config
     * 1)本地(localhost)访问时,能正常返回
     * 2)会出现404,因为访问的地址少了服务名:
     * 比如应该是“http://host:port/服务名/v3/api-docs”,但实际访问的是“http://host:port//v3/api-docs”
     */
    public class RewritePathSwaggerIndexPageTransformer extends SwaggerIndexPageTransformer {

        private SpringDocConfigProperties springDocConfigProperties;
        private SwaggerUiConfigParameters swaggerUiConfigParameters;
        /**
         * 上一次请求获取到的前缀
         */
        private String lastPrefix = Strings.EMPTY;

        public RewritePathSwaggerIndexPageTransformer(SwaggerUiConfigProperties swaggerUiConfig,
                                                      SwaggerUiOAuthProperties swaggerUiOAuthProperties, SwaggerUiConfigParameters swaggerUiConfigParameters,
                                                      SwaggerWelcomeCommon swaggerWelcomeCommon, ObjectMapperProvider objectMapperProvider,
                                                      SpringDocConfigProperties springDocConfigProperties) {
            super(swaggerUiConfig, swaggerUiOAuthProperties, swaggerUiConfigParameters, swaggerWelcomeCommon,
                    objectMapperProvider);
            this.springDocConfigProperties = springDocConfigProperties;
            this.swaggerUiConfigParameters = swaggerUiConfigParameters;
        }

        @Override
        public Resource transform(HttpServletRequest request, Resource resource,
                                  ResourceTransformerChain transformerChain) throws IOException {
            SpringDocConfigProperties.ApiDocs apiDocs = springDocConfigProperties.getApiDocs();
            String apiDocsPath = apiDocs.getPath();
            String configUrl = swaggerUiConfigParameters.getConfigUrl();
            String prefix = getPrefix(request);
            // 考虑同一个服务,可能有时候会被“走网关访问”,有时候会被“走IP+端口直接访问”,所以这里做了区分判断
            // 通过网关转发
            if (StringUtils.isNotBlank(prefix)) {
                // 上一次不是通过网关转发,即需要重新调整;如果上一次是通过网关转发,则不能调整,否则就叠加两次了
                if (!StringUtils.equals(lastPrefix, prefix)) {
                    String newApiDocsPath = prefix + apiDocsPath;
                    apiDocs.setPath(newApiDocsPath);
                    String newConfigUrl = RegExUtils.replaceFirst(configUrl, apiDocsPath, newApiDocsPath);
                    swaggerUiConfigParameters.setConfigUrl(newConfigUrl);
                    lastPrefix = prefix;
                }
            } else {
                // 不是通过网关转发
                // 上一次是通过网关转发,即需要重新调整
                if (!StringUtils.equals(lastPrefix, prefix)) {
                    // 去掉转发时,网关添加的路径
                    String newApiDocsPath = RegExUtils.replaceFirst(apiDocsPath, lastPrefix, "");
                    apiDocs.setPath(newApiDocsPath);
                    String newConfigUrl = RegExUtils.replaceFirst(configUrl, apiDocsPath, newApiDocsPath);
                    swaggerUiConfigParameters.setConfigUrl(newConfigUrl);
                    lastPrefix = prefix;
                }
            }
            return super.transform(request, resource, transformerChain);
        }

        /**
         * 获取网关转发时,url上添加的前缀
         */
        public String getPrefix(HttpServletRequest request) {
            // 获取网关转发的服务名
            return Optional.ofNullable(request.getHeader("x-forwarded-prefix")).orElse(Strings.EMPTY);
        }
    }
}

二、子服务集成

前提是子服务已经和eureka作好集成,通过网关能访问到子服务的api

maven坐标

<dependency>
    <groupId>com.github.xiaoymin</groupId>
    <artifactId>knife4j-openapi3-jakarta-spring-boot-starter</artifactId>
    <version>4.4.0</version>
</dependency>

<dependency>
    <groupId>io.springfox</groupId>
    <artifactId>springfox-boot-starter</artifactId>
    <version>3.0.0</version>
</dependency>

<dependency>
    <groupId>javax.servlet</groupId>
    <artifactId>javax.servlet-api</artifactId>
    <version>4.0.1</version>
    <scope>provided</scope>
</dependency>

配置文件中的配置,可能有些多余的,目前没有排除

server:
  port: 9100
  servlet:
    context-path: /service
springdoc:
  swagger-ui:
    path: /swagger-ui.html
    tags-sorter: alpha
    operations-sorter: alpha
  api-docs:
    path: /v3/api-docs
  group-configs:
    - group: 'service'
      paths-to-match: '/**'
      packages-to-scan: 'com.xxx.xxxx' #你的包路径,比如com.xxx.xxx.controller
# knife4j的增强配置,不需要增强可以不配
knife4j:
  enable: true
  setting:
    language: zh-CN

启动子服务就行,确保子服务自己的knife4j能访问到

至此集成完成。不需要任何配置类编写,就是引入maven坐标,整理好配置文件,启动类头上不需要任何关于knife4j的注解。

注意:如果eureka有Security管理,记得放开下面路径,没有引入Security应该不用管

/**
 * 配置要忽略的路径  这个在eureka项目的启动类中加就行
 */
@Bean
WebSecurityCustomizer webSecurityCustomizer() {
    // 忽略 /error /eureka/**
    return web -> web.ignoring().requestMatchers("/error","/eureka/**",
            "/swagger-ui.html","/webjars/**","/swagger-resources/**",
            "/v2/*","/doc.html",
            "/service/v3/api-docs","/v3/api-docs/swagger-config");
}

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

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

相关文章

LSTM反向传播及公式推导

先回顾一下正向传播的公式: 化简一下: 反向传播从下到上逐步求偏导: 对zt求偏导(预测值和标签值相减): zt对未知数wt,ht,bt分别求偏导: ht对ot,Ct求偏导: ot对Net0求偏导: Net0对w0,b0求偏导: .... 总体的思路就是那个公式从下到上逐步对未知数求偏导: 下面是总体的流程…

在Openshift(K8S)上通过EMQX Operator部署Emqx集群

EMQX Operator 简介 EMQX Broker/Enterprise 是一个云原生的 MQTT 消息中间件。 我们提供了 EMQX Kubernetes Operator 来帮助您在 Kubernetes 的环境上快速创建和管理 EMQX Broker/Enterprise 集群。 它可以大大简化部署和管理 EMQX 集群的流程&#xff0c;对于管理和配置的知…

微服务架构 --- 使用RabbitMQ进行异步处理

目录 一.什么是RabbitMQ&#xff1f; 二.异步调用处理逻辑&#xff1a; 三.RabbitMQ的基本使用&#xff1a; 1.安装&#xff1a; 2.架构图&#xff1a; 3.RabbitMQ控制台的使用&#xff1a; &#xff08;1&#xff09;Exchanges 交换机&#xff1a; &#xff08;2&#…

【双指针算法】快乐数

1.题目解析 2.算法分析 由图可知&#xff0c;不管是最后可以变成1的还是不可以变成1的都相当于形成环了&#xff0c;只是成环处值不一样 问题转变成&#xff0c;判断链表是否有环 采用双指针&#xff0c;快慢指针算法 1.定义快慢指针2.慢指针每次向后移动一步&#xff0c;快…

初识适配器模式

适配器模式 引入 生活中的例子&#xff1a;当我们使用手机充电时&#xff0c;充电器起到了转换器的作用&#xff0c;它将家用的220伏特电压转换成适合手机充电的5伏特电压。 适配器模式的三种类型 命名原则&#xff1a;适配器的命名应基于资源如何传递给适配器来进行。 类适配…

AnaTraf | 利用多点关联数据分析和网络关键KPI监控提升IT运维效率

目录 什么是多点关联数据分析&#xff1f; 多点关联数据分析的运用场景 监控网络关键KPI的重要性 典型的网络关键KPI 案例分析&#xff1a;利用多点关联数据分析和KPI监控解决网络性能问题 结语 AnaTraf 网络性能监控系统NPM | 全流量回溯分析 | 网络故障排除工具AnaTraf…

01 设计模式-创造型模式-工厂模式

工厂模式&#xff08;Factory Pattern&#xff09;是 Java 中最常用的设计模式之一&#xff0c;它提供了一种创建对象的方式&#xff0c;使得创建对象的过程与使用对象的过程分离。 工厂模式提供了一种创建对象的方式&#xff0c;而无需指定要创建的具体类。 通过使用工厂模式…

SpringBoot框架下的汽车票在线预订系统

4系统概要设计 4.1概述 本系统采用B/S结构(Browser/Server,浏览器/服务器结构)和基于Web服务两种模式&#xff0c;是一个适用于Internet环境下的模型结构。只要用户能连上Internet,便可以在任何时间、任何地点使用。系统工作原理图如图4-1所示&#xff1a; 图4-1系统工作原理…

基于单片机的家用无线火灾报警系统的设计

1 总体设计 本设计家用无线火灾报警系统利用单片机控制技术、传感器检测技术、GSM通信技术展开设计&#xff0c;如图2.1所示为本次系统设计的主体框图&#xff0c;系统包括单片机主控模块、温度检测模块、烟雾检测模块、按键模块、GSM通信模块、液晶显示模块、蜂鸣器报警模块。…

汽车票预订系统:SpringBoot框架的优势

6系统测试 6.1概念和意义 测试的定义&#xff1a;程序测试是为了发现错误而执行程序的过程。测试(Testing)的任务与目的可以描述为&#xff1a; 目的&#xff1a;发现程序的错误&#xff1b; 任务&#xff1a;通过在计算机上执行程序&#xff0c;暴露程序中潜在的错误。 另一个…

UE5 使用Animation Budget Allocator优化角色动画性能

Animation Budget Allocator是UE内置插件&#xff0c;通过锁定动画系统所占CPU的预算&#xff0c;在到达预算计算量时对动画进行限制与优化。 开启Animation Budget Allocator需要让蒙皮Mesh使用特定的组件&#xff0c;并进行一些编辑器设置即可开启。 1.开启Animation Budget…

地球链EACO怎么和房车旅游等行业结合起来加速全球发展?

地球链EACO怎么和房车旅游等行业结合起来加速全球发展&#xff1f; 将地球链&#xff08;EACO&#xff09;与房车,旅游&#xff0c;汽车等行业结合以加速全球发展&#xff0c;可以通过以下策略&#xff1a; 智能合约与租赁平台 去中心化租赁市场&#xff1a;建立一个基于EACO的…

PCL 点云配准 基于目标对称的ICP算法(精配准)

目录 一、概述 1.1原理 1.2实现步骤 1.3应用场景 二、代码实现 2.1关键函数 2.1.1计算点云的法线 2.1.2基于对称误差估计的ICP配准 2.1.3可视化 2.2完整代码 三、实现效果 PCL点云算法汇总及实战案例汇总的目录地址链接&#xff1a; PCL点云算法与项目实战案例汇总…

【火山引擎】调用火山大模型的方法 | SDK安装 | 配置 | 客户端初始化 | 设置

豆包 (Doubao) 是字节跳动研发的大规模预训练语言模型。 目录 1 安装 2 配置访问凭证 3 客户端初始化 4 设置地域和访问域名 5 设置超时/重试次数 1 安装 通过pip安装PYTHON SDK。 pip install volcengine-python-sdk[ark] 2 配置访问凭证 获取 API Key 访问凭证具体步…

理工科考研想考计算机,湖南大学、重大、哈工大威海、山东大学,该如何选择?

C哥专业提供——计软考研院校选择分析专业课备考指南规划 计算机对理工科同学来说&#xff0c;还是性价比很高的&#xff0c;具有很大的优势&#xff01; 一、就业前景广阔 高需求行业 在当今数字化时代&#xff0c;计算机技术几乎渗透到了各个领域&#xff0c;无论是互联网…

YOLO11 目标检测 | 自动标注 | 预标注 | 标签格式转换 | 手动校正标签

本文分享使用YOLO11进行目标检测时&#xff0c;实现模型推理预标注、自动标注、标签格式转换、以及使用Labelme手动校正标签等功能。 目录 1、预训练权重 2、生成预标注 3、分析YOLO11的目标检测格式 4、分析Labelme标注工具的格式 5、生成json标注文件 6、手动校正标签 …

SQL Server-导入和导出excel数据-注意事项

环境&#xff1a; win10&#xff0c;SQL Server 2008 R2 之前写过的放在这里&#xff1a; SqlServer_陆沙的博客-CSDN博客 https://blog.csdn.net/pxy7896/category_12704205.html 最近重启ASP.NET项目&#xff0c;在使用sql server导出和导入数据时遇到一些问题&#xff0c;特…

Qt键盘按下事件和定时器事件及事件的接收和忽略

定时器事件 //设置多少毫秒调用一次 1s1000timerId this->startTimer(1000);timerId2 this->startTimer(500);void MyWidget::timerEvent(QTimerEvent* t) {static int sec 0;//通过判断当前ID来实现不同定时器的调用时间if(t->timerId() this->timerId){//隔一…

AtCoder Beginner Contest 375 A-E 题解

我的老师让我先做最后再交&#xff0c;看正确率&#xff08;即以OI赛制打abc&#xff09; 所以我用的小号&#xff08;… …&#xff09; C 卡了老半天才出来&#xff0c;我把题读错了 难度&#xff1a; A. Seats 题意 给你一个字符串 S S S&#xff0c;仅包含 . 和 #&…

kubernets(二)

集群操作 查看集群信息 kubectl get查看各组件信息 格式&#xff1a;kubectl get 资源类型 【资源名】 【选项】 events #查看集群中的所有日志信息 -o wide # 显示资源详细信息&#xff0c;包括节点、地址... -o yaml/json #将当前资源对象输出至 yaml/json 格式文…