spring - 使用 SpringBoot、Gateway 和 SpringFox Swagger 在微服务中集中 Swagger

标签 spring cloud swagger swagger-ui gateway

我的用户 Spring Cloud Gateway 女巫基于 Webflux,在我的微服务环境中,每个服务都有自己的带有 UI 的 Swagger ......到目前为止没有问题。现在我将所有 Swagger 集中到我的网关中,我发现了大量 Zuul 网关的示例代码......我认为这会起作用。但是找不到 spring.cloud.Gateway 女巫的任何示例基于响应式(Reactive) Webflux 界面,使用“springfox:springfox-spring-webflux:3.0.0-SNAPSHOT”依赖项,我得到了 SwaggerUI,但我无法集中所有我来自其他微服务的 Swagger 我不知道如何配置 SwaggerResourcesProvider ...

我不知道我是否应该做一个自己的微服务(没有 Webflux)来处理所有的 Swagger,我认为这不是问题。
问题是 WebFlux 的事情:-)

也许有人建议我制作自己的微服务(这应该可行,但我不确定这是否过分)。或者有人对我的问题有解决方案。

最佳答案

我遇到了同样的问题,但我没有找到一个干净的解决方案,因为 Swagger 之间没有集成和 Webflux然而。

另一方面,我成功地设置了一个最小配置来为 swagger 创建代理。

首先你需要创建一个 Controller 暴露 Swagger API和资源:


@Controller
public class SwaggerController {
    private final JsonSerializer jsonSerializer;
    private final SwaggerResourcesProvider swaggerResources;

    @Autowired
    public SwaggerController(JsonSerializer jsonSerializer, SwaggerResourcesProvider swaggerResources) {
        this.jsonSerializer = jsonSerializer;
        this.swaggerResources = swaggerResources;
    }

    @RequestMapping({"/swagger-resources/configuration/security"})
    @ResponseBody
    public ResponseEntity<SecurityConfiguration> securityConfiguration() {
        return ResponseEntity.ok(SecurityConfigurationBuilder.builder().build());
    }

    @RequestMapping({"/swagger-resources/configuration/ui"})
    @ResponseBody
    public ResponseEntity<UiConfiguration> uiConfiguration() {
        return ResponseEntity.ok(UiConfigurationBuilder.builder().build());
    }

    @RequestMapping({"/swagger-resources"})
    @ResponseBody
    public ResponseEntity<List<SwaggerResource>> swaggerResources() {
        return ResponseEntity.ok(this.swaggerResources.get());
    }

    @RequestMapping(
        value = {"/v2/api-docs"},
        method = {RequestMethod.GET},
        produces = {"application/json", "application/hal+json"}
    )
    @ResponseBody
    public ResponseEntity<Json> getDocumentation() {
        Swagger swagger = new Swagger();
        return ResponseEntity.ok(this.jsonSerializer.toJson(swagger));
    }
}

接下来,您需要一个 swagger 配置来从您的微服务创建 Swagger 资源:
package fr.samse.bravo.rechercheProduit.gateway.config;

import org.springframework.cloud.gateway.config.GatewayProperties;
import org.springframework.cloud.gateway.route.RouteDefinition;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Lazy;
import org.springframework.context.annotation.Primary;
import springfox.documentation.spring.web.json.JacksonModuleRegistrar;
import springfox.documentation.spring.web.json.JsonSerializer;
import springfox.documentation.swagger.web.SwaggerResource;
import springfox.documentation.swagger.web.SwaggerResourcesProvider;

import java.util.List;
import java.util.Objects;
import java.util.Optional;
import java.util.stream.Collectors;

@Configuration
public class SwaggerConfig {

    private final GatewayProperties properties;

    public SwaggerConfig(GatewayProperties properties) {
        this.properties = properties;
    }

    @Bean
    public JsonSerializer jsonSerializer(List<JacksonModuleRegistrar> moduleRegistrars) {
        return new JsonSerializer(moduleRegistrars);
    }

    @Primary
    @Bean
    @Lazy
    public SwaggerResourcesProvider swaggerResourcesProvider() {
        return () -> properties.getRoutes().stream()
            .map(route -> createResource(route.getId(), getRouteLocation(route), "2.0"))
            .filter(Objects::nonNull)
            .collect(Collectors.toList());
    }

    // You will certainly need to edit this
    private String getRouteLocation(RouteDefinition route) {
        return Optional.ofNullable(route.getPredicates().get(0).getArgs().values().toArray()[0])
            .map(String::valueOf)
            .map(s -> s.replace("*", ""))
            .orElse(null);
    }

    private SwaggerResource createResource(String name, String location, String version) {
        SwaggerResource swaggerResource = new SwaggerResource();
        swaggerResource.setName(name);
        swaggerResource.setLocation(location + "/v2/api-docs");
        swaggerResource.setSwaggerVersion(version);
        return swaggerResource;
    }
}


我认为如果您使用服务发现服务器,此解决方案将不起作用,但就我而言,我不需要,因为我有 spring.cloud.gateway.routes 的配置:
 - id: api-client
   uri: lb://client
   predicates:
      - Path=/api/client/**

这可以很容易地适应从 Eureka 或 Consul 获取服务位置。

让我知道它是否有效。如果有人找到了另一种选择,我很感兴趣。

关于spring - 使用 SpringBoot、Gateway 和 SpringFox Swagger 在微服务中集中 Swagger,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56369090/

相关文章:

java - 如何从 JPA 查询更新 MySQL 表时间戳?

Spring Cloud 多个 RestTemplate

node.js - 没有多个Redis的多个服务器上的socket.io

json - 为同一项目中的多个 swagger 生成代码

api - Swagger Codegen 没有 null 的属性

asp.net-core - 在 Asp.net Core 中使用 Swagger 进行流畅验证

java - 将特定 bean 作为参数注入(inject)具有多个参数的函数中

java - Spring Data 不记录 findById

spring - 文件上传 API 在 Postman 中有效,但在 React JS 中无效

cloud - 虚拟化环境中的时间依赖性是什么?