Intégration de la documentation d'API Knife4j via Spring Cloud Gateway avec Spring Cloud Alibaba

Résultat attendu :

Le service Gateway permet d’accéder à la documentation Swagger/Knife4j de plusieurs microservices en un seul point d’entrée.

Dépendance Knife4j :

<dependency>
    <groupId>com.github.xiaoymin</groupId>
    <artifactId>knight4j-spring-boot-starter</artifactId>
    <version>3.0.3</version>
</dependency>

Implémentation personnalisée de SwaggerResourcesProvider :

Cette classe récupère les routes configurées dans le gateway et construit dynamiquement les ressources Swagger correspondantes.

import lombok.RequiredArgsConstructor;
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;

@Primary
@Component
@RequiredArgsConstructor
public class CustomSwaggerResourcesProvider implements SwaggerResourcesProvider {

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

    private final RouteLocator routeLocator;
    private final GatewayProperties gatewayProperties;

    @Override
    public List<SwaggerResource> get() {
        List<String> activeRouteIds = new ArrayList<>();
        routeLocator.getRoutes().subscribe(route -> activeRouteIds.add(route.getId()));

        List<SwaggerResource> resources = new ArrayList<>();
        gatewayProperties.getRoutes().stream()
            .filter(routeDef -> activeRouteIds.contains(routeDef.getId()))
            .forEach(routeDef -> routeDef.getPredicates().stream()
                .filter(predDef -> "Path".equalsIgnoreCase(predDef.getName()))
                .forEach(predDef -> {
                    String pathTemplate = predDef.getArgs().get(NameUtils.GENERATED_NAME_PREFIX + "0");
                    String swaggerPath = pathTemplate.replace("/**", SWAGGER_API_PATH);
                    resources.add(buildSwaggerResource(routeDef.getId(), swaggerPath));
                }));
        return resources;
    }

    private SwaggerResource buildSwaggerResource(String name, String location) {
        SwaggerResource resource = new SwaggerResource();
        resource.setName(name);
        resource.setLocation(location);
        resource.setSwaggerVersion("2.0");
        return resource;
    }
}

Contrôleur pour exposer /swagger-resources :

Ce contrôleur remplace le point de terminaison par défaut pour retourner les ressources Swagger générées dynamiquement.

import lombok.RequiredArgsConstructor;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import springfox.documentation.swagger.web.SwaggerResource;

import java.util.List;

@RestController
@RequiredArgsConstructor
public class SwaggerResourceEndpoint {

    private final CustomSwaggerResourcesProvider swaggerProvider;

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

Étiquettes: Spring Cloud Gateway Knife4j Swagger Spring Cloud Alibaba API Documentation

Publié le 15 septembre à 02h18