【Knife4j】小試牛刀色建,基于gateway的集成

上回書說到,knife4j基于注冊中心eureka集成舌缤,由于有些小伙伴可能使用了nacos箕戳、Consul某残、zk等注冊中心,均有對應的集成方法陵吸,但是一旦切換了注冊中心(比如從eureka切換成nacos)玻墅,則需要重新做集成。因此本文介紹一下基于gateway的集成方式壮虫。

一澳厢、工程結構

  • eboot-center:eureka注冊中心(服務端)
    eboot-knife4j:文檔服務,本文不需要
    eboot-common:包含了一些基礎的認證囚似、全局異常等處理剩拢,本文暫不需要
  • eboot-gateway:spring-cloud-gateway,大多是情況下微服務均走網關
  • eboot-modulars:即各個業(yè)務子系統(tǒng)饶唤,這里分了三個:認證管理徐伐、文件管理、系統(tǒng)管理
    eboo-ui:前端項目募狂,本文不需要
    image.png

二办素、center、modulars配置

均參考上篇文章即可祸穷,可回頭看《【Knife4j】小試牛刀性穿,基于eureka的集成

三、gateway聚合配置

此處建議先看官網配置
pom配置

      <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-gateway</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
        </dependency>
        <dependency>
            <groupId>com.github.xiaoymin</groupId>
            <artifactId>knife4j-spring-boot-starter</artifactId>
        </dependency>

原springboot基于tomcat雷滚,而gateway基于webflux需曾,因此需要以下操作:
springfox-swagger提供的分組接口是swagger-resource,返回的是分組接口名稱、地址等信息揭措。在Spring Cloud微服務架構下,我們需要重寫該接口,主要是通過網關的注冊中心動態(tài)發(fā)現所有的微服務文檔,代碼如下:

package com.mos.eboot.gateway.config.properties;

import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
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;

/**
 * swagger資源配置
 *
 * @author 小塵哥
 * @date 2022/05/30
 */
@Slf4j
@AllArgsConstructor
@Component
@Primary
public class SwaggerResourceConfig implements SwaggerResourcesProvider {

    private final RouteLocator routeLocator;
    private final GatewayProperties gatewayProperties;

    @Override
    public List<SwaggerResource> get() {
        List<SwaggerResource> resources = new ArrayList<>();
        List<String> routes = new ArrayList<>();
        routeLocator.getRoutes().subscribe(route -> routes.add(route.getId()));
        gatewayProperties.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")
                                    .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(name);
        swaggerResource.setLocation(location);
        swaggerResource.setSwaggerVersion("2.0");
        return swaggerResource;
    }
}

接口如下

package com.mos.eboot.gateway.handler;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import reactor.core.publisher.Mono;
import springfox.documentation.swagger.web.*;

import java.util.Optional;

@RestController
public class SwaggerHandler {

    @Autowired(required = false)
    private SecurityConfiguration securityConfiguration;

    @Autowired(required = false)
    private UiConfiguration uiConfiguration;

    private final SwaggerResourcesProvider swaggerResources;

    @Autowired
    public SwaggerHandler(SwaggerResourcesProvider swaggerResources) {
        this.swaggerResources = swaggerResources;
    }


    @GetMapping("/swagger-resources/configuration/security")
    public Mono<ResponseEntity<SecurityConfiguration>> securityConfiguration() {
        return Mono.just(new ResponseEntity<>(
                Optional.ofNullable(securityConfiguration).orElse(SecurityConfigurationBuilder.builder().build()), HttpStatus.OK));
    }

    @GetMapping("/swagger-resources/configuration/ui")
    public Mono<ResponseEntity<UiConfiguration>> uiConfiguration() {
        return Mono.just(new ResponseEntity<>(
                Optional.ofNullable(uiConfiguration).orElse(UiConfigurationBuilder.builder().build()), HttpStatus.OK));
    }

    @GetMapping("/swagger-resources")
    public Mono<ResponseEntity> swaggerResources() {
        return Mono.just((new ResponseEntity<>(swaggerResources.get(), HttpStatus.OK)));
    }
}

yaml配置(基于yaml中的routes進行分組)

server:
  port: 9005
eureka:
  client:
    serviceUrl:
      defaultZone: http://localhost:8761/eureka/
  instance:
    appname: eboot-gateway
    leaseRenewalIntervalInSeconds: 1
    lease-expiration-duration-in-seconds: 2
    prefer-ip-address: true
    instance-id: 127.0.0.1:9005
spring:
  main:
    allow-bean-definition-overriding: true
    allow-circular-references: true
    web-application-type: REACTIVE
  cloud:
    gateway:
      discovery:
        locator:
          # gateway開啟服務注冊和發(fā)現的功能,
          enabled: true
          # 將請求路徑上的服務名配置為小寫(因為服務注冊的時候刻蚯,向注冊中心注冊時將服務名轉成大寫的了)
          lowerCaseServiceId: true
      routes:
        - id: boot-system
          uri: http://localhost:9093
          predicates:
            - Path=/system/**
       #   filters:
        #    - SwaggerHeaderFilter
       #     - StripPrefix=1
        - id: eboot-auth
          uri: http://localhost:9091
          predicates:
            - Path=/auth/**

四绊含、展示

image.png

五、注意點

在集成Spring Cloud Gateway網關的時候,會出現沒有basePath的情況(即定義的例如/user炊汹、/order等微服務的前綴),這個情況在使用zuul網關的時候不會出現此問題,因此,在Gateway網關需要添加一個Filter實體Bean

由于我使用的springcloud版本為3.1.2躬充,未出現該問題,若出現請參考官網的解決方案讨便,添加以下過濾器,同時放開yaml中的routes.filters配置項

@Component
public class SwaggerHeaderFilter extends AbstractGatewayFilterFactory {
    private static final String HEADER_NAME = "X-Forwarded-Prefix";

    private static final String URI = "/v2/api-docs";

    @Override
    public GatewayFilter apply(Object config) {
        return (exchange, chain) -> {
            ServerHttpRequest request = exchange.getRequest();
            String path = request.getURI().getPath();
            if (!StringUtils.endsWithIgnoreCase(path,URI )) {
                return chain.filter(exchange);
            }
            String basePath = path.substring(0, path.lastIndexOf(URI));
            ServerHttpRequest newRequest = request.mutate().header(HEADER_NAME, basePath).build();
            ServerWebExchange newExchange = exchange.mutate().request(newRequest).build();
            return chain.filter(newExchange);
        };
    }
}
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
  • 序言:七十年代末充甚,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子霸褒,更是在濱河造成了極大的恐慌伴找,老刑警劉巖,帶你破解...
    沈念sama閱讀 207,113評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件废菱,死亡現場離奇詭異技矮,居然都是意外死亡抖誉,警方通過查閱死者的電腦和手機,發(fā)現死者居然都...
    沈念sama閱讀 88,644評論 2 381
  • 文/潘曉璐 我一進店門衰倦,熙熙樓的掌柜王于貴愁眉苦臉地迎上來袒炉,“玉大人,你說我怎么就攤上這事樊零∥掖牛” “怎么了?”我有些...
    開封第一講書人閱讀 153,340評論 0 344
  • 文/不壞的土叔 我叫張陵驻襟,是天一觀的道長夺艰。 經常有香客問我,道長塑悼,這世上最難降的妖魔是什么劲适? 我笑而不...
    開封第一講書人閱讀 55,449評論 1 279
  • 正文 為了忘掉前任,我火速辦了婚禮厢蒜,結果婚禮上霞势,老公的妹妹穿的比我還像新娘。我一直安慰自己斑鸦,他們只是感情好愕贡,可當我...
    茶點故事閱讀 64,445評論 5 374
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著巷屿,像睡著了一般固以。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上嘱巾,一...
    開封第一講書人閱讀 49,166評論 1 284
  • 那天憨琳,我揣著相機與錄音,去河邊找鬼旬昭。 笑死篙螟,一個胖子當著我的面吹牛,可吹牛的內容都是我干的问拘。 我是一名探鬼主播遍略,決...
    沈念sama閱讀 38,442評論 3 401
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼骤坐!你這毒婦竟也來了绪杏?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 37,105評論 0 261
  • 序言:老撾萬榮一對情侶失蹤纽绍,失蹤者是張志新(化名)和其女友劉穎蕾久,沒想到半個月后,有當地人在樹林里發(fā)現了一具尸體拌夏,經...
    沈念sama閱讀 43,601評論 1 300
  • 正文 獨居荒郊野嶺守林人離奇死亡腔彰,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 36,066評論 2 325
  • 正文 我和宋清朗相戀三年叫编,在試婚紗的時候發(fā)現自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片霹抛。...
    茶點故事閱讀 38,161評論 1 334
  • 序言:一個原本活蹦亂跳的男人離奇死亡搓逾,死狀恐怖,靈堂內的尸體忽然破棺而出杯拐,到底是詐尸還是另有隱情霞篡,我是刑警寧澤,帶...
    沈念sama閱讀 33,792評論 4 323
  • 正文 年R本政府宣布端逼,位于F島的核電站朗兵,受9級特大地震影響,放射性物質發(fā)生泄漏顶滩。R本人自食惡果不足惜余掖,卻給世界環(huán)境...
    茶點故事閱讀 39,351評論 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望礁鲁。 院中可真熱鬧盐欺,春花似錦、人聲如沸仅醇。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,352評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽析二。三九已至粉洼,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間叶摄,已是汗流浹背属韧。 一陣腳步聲響...
    開封第一講書人閱讀 31,584評論 1 261
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留蛤吓,地道東北人宵喂。 一個月前我還...
    沈念sama閱讀 45,618評論 2 355
  • 正文 我出身青樓,卻偏偏與公主長得像柱衔,于是被迫代替她去往敵國和親樊破。 傳聞我的和親對象是個殘疾皇子愉棱,可洞房花燭夜當晚...
    茶點故事閱讀 42,916評論 2 344

推薦閱讀更多精彩內容