Nacos+Gateway+Springdoc 集中管理API


Spring cloud Gateway 基於使用Netty作為內嵌服務器,而Netty基於WebFlux實現,因此如果想要springdoc的 Swagger UI 顯示在網關微服務中,需要用到它的WebFlux UI庫。

現有三個微服務項目,分別是gateway-serviceshop-serviceuser-service,各依賴庫版本如下:

依賴 版本
spring boot 2.6.1
spring cloud 2021.0.0
spring cloud alibaba 2021.1
springdoc openapi 1.5.13

由於只在gateway-service網關微服務上查看 Swagger UI 頁面,因此另外兩個業務微服務中只需要添加springdoc openapi的核心依賴庫即可:

...
<dependency>
	<groupId>org.springdoc</groupId>
	<artifactId>springdoc-openapi-webmvc-core</artifactId>
	<version>${springdoc.version}</version>
</dependency>
...

gateway-service中除了spring cloud gateway之外,還需要添加springdoc openapi webflux依賴:

...
<dependency>
	<groupId>org.springframework.cloud</groupId>
	<artifactId>spring-cloud-starter-gateway</artifactId>
</dependency>
<!-- spring cloud 2020之后的版本中不再自動引入Ribbon依賴,需要手動引入loadbalancer 否則會出現503錯誤 -->
<dependency>
	<groupId>org.springframework.cloud</groupId>
	<artifactId>spring-cloud-starter-loadbalancer</artifactId>
</dependency>
<dependency>
	<groupId>org.springdoc</groupId>
	<artifactId>springdoc-openapi-webflux-ui</artifactId>
	<version>${springdoc.version}</version>
</dependency>
...

user-serviceshop-service中進行服務注冊、數據庫連接等基礎配置:

...
spring:
  application:
    name: user-service
  cloud:
    nacos:
      discovery:
        server-addr: localhost:8848
...

同時編寫 Swagger 自定義配置類:

@Configuration
public class SpringDocConfig {
    @Bean
    public OpenAPI customOpenApi() {
        return new OpenAPI().info(new Info().title("User API")
                        .description("User API")
                        .version("v1.0.0")
                        .contact(new Contact()
                                .name("姓名")
                                .email("郵箱")));
    }
}

此時已經可以通過訪問http://IP:微服務端口/v3/api-docs/來獲取到openapi的 JSON 格式數據了。

接下來需要在gateway-service中獲取到其他服務的名稱,然后按服務名進行分組,可以參考 springdoc 微服務 demo 中的代碼:

@Configuration
public class SpringDocConfig {
    @Bean
    @Lazy(false)
    public List<GroupedOpenApi> apis(SwaggerUiConfigParameters swaggerUiConfigParameters, RouteDefinitionLocator locator) {
        List<GroupedOpenApi> groups = new ArrayList<>();
        List<RouteDefinition> definitions = locator.getRouteDefinitions().collectList().block();

        definitions.stream().filter(routeDefinition -> routeDefinition.getId().matches(".*-service"))
                .forEach(routeDefinition -> {
                    String name = routeDefinition.getId().replaceAll("-service", "");
                    swaggerUiConfigParameters.addGroup(name);
                    GroupedOpenApi.builder().pathsToMatch("/" + name + "/**").group(name).build();
                });
        return groups;
    }

    @Bean
    public OpenAPI customOpenApi() {
        return new OpenAPI().info(new Info().title("springdoc gateway API")
                        .description("springdoc gateway API")
                        .version("v1.0.0")
                        .contact(new Contact()
                                .name("姓名")
                                .email("郵箱")));
    }
}

這個配置可以將一個服務下的 API 按照服務名分組,通過http://IP:網關端口/v3/api-docs/組名可以訪問對應 API 數據。為了使請求路徑更符合項目規范,將/v3/api-docs/組名改為/組名/v3/api-docs,需要對路由進行重寫:

...
spring:
  application:
    name: gateway-service
  cloud:
    nacos:
      server-addr: localhost:8848
    gateway:
      discovery:
        locator:
          enabled: true
      routes:
        - id: user-route
          uri: lb://user-service
          predicates:
            - Path=/user/**
          filters:
            - RewritePath=/user/(?<path>.*),/$\{path}
        - id: shop-route
          uri: lb://shop-service
          predicates:
            - Path=/shop/**
          filters:
            - RewritePath=/shop/(?<path>.*),/$\{path}
        - id: openapi
          uri: http://localhost:${server.port}
          predicates:
            - Path=/v3/api-docs/**
          filters:
            - RewritePath=/v3/api-docs/(?<path>.*),/$\{path}/v3/api-docs

springdoc:
  swagger-ui:
    use-root-path: true
    urls:
      - name: user
        url: /v3/api-docs/user
      - name: shop
        url: /v3/api-docs/shop
...

至此,springdoc openapi在 Spring Cloud Gateway 中的聚合已經完成了,通過網關微服務的swagger-ui.html即可查看項目中其他微服務下的 API 接口。

另:如果在 Swagger UI 中使用 "Try it out" 功能出現跨域請求的錯誤,則需要額外進行一下配置

  1. 在 Controller 上添加@CrossOrigin注解,例:

    @RestController
    @CrossOrigin
    public class UserController {
        ...
    }
    
  2. 在網關微服務application.yml中添加配置:

    spring:
      cloud:
        gateway:
          globalcors:
            cors-configurations:
              '[/**]':
                allowedOrigins: "*"
                allowedMethods:
                  - GET
                  - POST
                  - PUT
                  - DELETE
                  - OPTIONS
    


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM