Spring Cloud Gateway 整合 OpenAPI

1、概览

文档是构建任何健壮的 REST API 的重要部分。我们可以基于 OpenAPI 规范实现 API 文档,并在 Spring 应用中使用 Swagger UI 进行可视化展示。

此外,由于 API 端点可以通过 API 网关公开,我们还需要将后端服务的 OpenAPI 文档与网关服务集成。网关服务将提供所有 API 文档的汇总视图。

本文将带你了解如何在 Spring 应用中集成 OpenAPI,以及如何使用 Spring Cloud Gateway 服务公开后端服务的 API 文档。

2、示例应用

假设我们需要构建一个简单的微服务来获取一些数据。

2.1、Maven 依赖

首先,添加 spring-boot-starter-web 依赖:

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
    <version>3.3.2</version>
</dependency>

2.2、实现 REST API

我们的后端应用有一个端点返回 Product 数据。

首先,创建 Product 类:

public class Product {
    private long id;
    private String name;
    // 标准 Getter / Setter
}

接下来,在 ProductController 中实现 getProduct 端点:

@GetMapping(path = "/product/{id}")
public Product getProduct(@PathVariable("id") long productId){
    LOGGER.info("Getting Product Details for Product Id {}", productId);
    return productMap.get(productId);
}

3、Spring 整合 OpenAPI

OpenAPI 3.0 规范可通过 springdoc-openapi starter 项目与 Spring Boot 3 集成。

3.1、Springdoc 依赖

Spring Boot 3.x 要求使用 version 2springdoc-openapi-starter-webmvc-ui 依赖:

<dependency>
    <groupId>org.springdoc</groupId>
    <artifactId>springdoc-openapi-starter-webmvc-ui</artifactId>
    <version>2.6.0</version>
</dependency>

3.2、配置 OpenAPI 定义

我们可以通过一些 swagger 注解来自定义 OpenAPI 定义的详细信息,如标题、描述和版本。

@OpenAPI Bean 配置一些属性,并设置 @OpenAPIDefinition 注解:

@OpenAPIDefinition
@Configuration
public class OpenAPIConfig {

    @Bean
    public OpenAPI customOpenAPI() {
        return new OpenAPI()
          .servers(List.of(new Server().url("http://localhost:8080")))
          .info(new Info().title("Product Service API").version("1.0.0"));
    }
}

3.3、配置 OpenAPI 和 Swagger UI 路径

OpenAPI 和 Swagger UI 默认路径可通过 springdoc-openapi 配置进行自定义。

springdoc-openapi 属性中包含特定于 product 的路径:

springdoc:
  api-docs:
    enabled: true 
    path: /product/v3/api-docs
  swagger-ui:
    enabled: true
    path: /product/swagger-ui.html

在任何环境下,我们都可以配置 enabledfalse 来禁用 OpenAPI 的 api-docs 和 Swagger UI 功能:

springdoc:
  api-docs:
    enabled: false
  swagger-ui:
    enabled: false

3.4、添加 API 摘要

我们可以配置 API 摘要和 Payload 详情,并添加任何与安全相关的信息。

ProductController 类中加入 API 操作摘要详情:

@Operation(summary = "Get a product by its id")
    @ApiResponses(value = {
      @ApiResponse(responseCode = "200", description = "Found the product",
        content = { @Content(mediaType = "application/json", 
          schema = @Schema(implementation = Product.class)) }),
      @ApiResponse(responseCode = "400", description = "Invalid id supplied",
        content = @Content),
      @ApiResponse(responseCode = "404", description = "Product not found",
        content = @Content) })
@GetMapping(path = "/product/{id}")
public Product getProduct(@Parameter(description = "id of product to be searched") 
  @PathVariable("id") long productId){

在上述代码中,我们设置了 API 操作摘要以及 API 请求和响应参数说明。

后端服务已与 OpenAPI 集成,现在我们将实现一个 API 网关服务。

4、使用 Spring Cloud Gateway 实现网关

现在,使用 Spring Cloud Gateway 支持来实现 API 网关服务。API 网关服务将向用户公开 Product API。

4.1、Spring Cloud Gateway 依赖

首先,添加 spring-cloud-starter-gateway 依赖:

<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-gateway</artifactId>
    <version>4.1.5</version
</dependency>

4.2、配置 API 路由

我们可以使用 Spring Cloud Gateway 路由选项公开 Product Service 端点。

使用 /product 路径配置 predicates,并使用后端 URI http://<hostname>:<port> 设置 uri 属性:

spring:
  cloud:
    gateway:
      routes:
        -   id: product_service_route
            predicates:
              - Path=/product/**
            uri: http://localhost:8081

在任何生产就绪的应用中,Spring Cloud Gateway 应该路由到后端服务的负载均衡器(Balancer) URL

4.3、测试 Spring Gateway API

运行 Product 和网关这两个服务:

$ java -jar ./spring-backend-service/target/spring-backend-service-1.0.0-SNAPSHOT.jar
$ java -jar ./spring-cloud-gateway-service/target/spring-cloud-gateway-service-1.0.0-SNAPSHOT.jar

现在,通过网关服务 URL 访问 /product 端点:

$ curl -v 'http://localhost:8080/product/100001'

< HTTP/1.1 200 OK
< Content-Type: application/json
{"id":100001,"name":"Apple"}

如上,我们可以获取到后端 API 的响应。

5、Spring Gateway Service 整合 OpenAPI

现在,将 Spring Gateway 应用与 OpenAPI 文档整合在一起,就像在 Product 服务中实现的那样。

5.1、springdoc-openapi 依赖

这需要添加 springdoc-openapi-starter-webflux-ui 依赖,而不是 springdoc-openapi-starter-webmvc-ui 依赖:

<dependency>
    <groupId>org.springdoc</groupId>
    <artifactId>springdoc-openapi-starter-webflux-ui</artifactId>
    <version>2.6.0</version>
</dependency>

注意,Spring Cloud Gateway 需要 webflux-ui 依赖项,因为它基于 Spring WebFlux 项目。

5.2、配置 OpenAPI 定义

配置一个 OpenAPI Bean,包含一些与摘要相关细节:

@OpenAPIDefinition
@Configuration
public class OpenAPIConfig {

    @Bean
    public OpenAPI customOpenAPI() {
        return new OpenAPI().info(new Info()
          .title("API Gateway Service")
          .description("API Gateway Service")
          .version("1.0.0"));
    }
}

5.3、配置 OpenAPI 和 Swagger UI 路径

在网关服务中自定义 OpenAPI api-docs.pathswagger-ui.urls 属性:

springdoc:
  api-docs:
    enabled: true
    path: /v3/api-docs
  swagger-ui:
    enabled: true
    config-url: /v3/api-docs/swagger-config
    urls:
      -   name: gateway-service
          url: /v3/api-docs

5.4、包含 OpenAPI URL 引用

要从网关服务访问 Product 服务 api-docs 端点,需要在上述配置中添加其路径。

在上述 springdoc.swagger-ui.urls 属性中包含 /product/v3/api-docs 路径:

springdoc:
  swagger-ui:
    urls:
      -   name: gateway-service
          url: /v3/api-docs
      -   name: product-service
          url: /product/v3/api-docs

6、在 API Gateway 应用中测试 Swagger UI

运行这两个应用后,我们可以通过浏览器访问 http://localhost:8080/swagger-ui.html,在 Swagger UI 中查看 API 文档:

Gateway_Swagger_UI

现在,从右上角的下拉菜单中访问 Product 服务 api-docs

Product 服务的 OpenAPI 定义

通过上述页面,我们可以查看并访问 Product 服务 API 端点。

我们可以请求 http://localhost:8080/product/v3/api-docs 端点,以 JSON 格式访问 Product 服务 API 文档。

7、总结

本文介绍了如何在 Spring 应用中使用 springdoc-openapi 支持来实现 OpenAPI 文档,以及如何在 Spring Cloud Gateway 服务中公开后端 API 文档。

最后,演示了如何通过 Spring Gateway 服务的 Swagger UI 页面访问 OpenAPI 文档。


Ref:https://www.baeldung.com/spring-cloud-gateway-integrate-openapi