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());
}
}