Централизованный Swagger в MicroServices с SpringBoot, Gateway и SpringFox Swagger - PullRequest
1 голос
/ 30 мая 2019

Я использую Spring Cloud Gateway, основанный на Webflux, в моей среде MicroService у каждой Службы есть собственный Swagger с пользовательским интерфейсом ... Пока никаких проблем. Теперь я бы централизовал все Swagger на один в моем шлюзе, я нашел тонны примера кода для Zuul Gateway ... Я думаю, это будет работать. Но я не могу найти никакого примера для ведьмы spring.cloud.Gateway, основанной на реактивном интерфейсе Webflux, с зависимостью 'springfox: springfox-spring-webflux: 3.0.0-SNAPSHOT'. Я получаю SwaggerUI, но не могу централизовать все мой Swagger от другого MicroService я не знаю, как настроить SwaggerResourcesProvider ...

Я не знаю, должен ли я сделать собственный MicroService (без Webflux) для обработки всех Swaggers, я думаю, что это не будет проблемой. Проблема в WebFlux: -)

Может быть, у кого-то есть рекомендация, если я сделаю собственный MicroService (это должно работать, но я не уверен, что это слишком). Или у кого-то есть решение моей проблемы.

1 Ответ

0 голосов
/ 25 июля 2019

Я столкнулся с той же проблемой и не нашел чистого решения, потому что пока нет интеграции между Swagger и Webflux.

С другой стороны, мне удаетсяустановите минимальную конфигурацию для создания прокси для swagger.

Сначала вам нужно создать контроллер, предоставляющий 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;
    }
}

Я думаю, что это решение не будет работать, если вы используете сервер Service Discovery, но в моем случае мне это не нужно, потому что у меня есть конфигурация для spring.cloud.gateway.routes:

 - id: api-client
   uri: lb://client
   predicates:
      - Path=/api/client/**

Это можно легко адаптировать для получения местоположения службы у Эврики или Консула.

Дайте мне знать, если это работает.И если кто-то найдет другую альтернативу, мне будет интересно.

...