记录下 OpenApi3 + SpringCloud Gateway 聚合文档的过程
组件选型
- SpringDoc
- Knife4j
- SpringCloud Gateway
项目配置
在所有的 spring boot 项目中引入 SpringDoc
1 2 3 4 5
| <dependency> <groupId>org.springdoc</groupId> <artifactId>springdoc-openapi-ui</artifactId> <version>${springdoc.version}</version> </dependency>
|
在 gateway 项目中引入 SpringDoc
1 2 3 4 5
| <dependency> <groupId>org.springdoc</groupId> <artifactId>springdoc-openapi-webflux-ui</artifactId> <version>${springdoc.version}</version> </dependency>
|
并且需要排除 springdoc-openapi-ui 的依赖
OpenAPI 配置
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| @Configuration @AllArgsConstructor public class SwaggerConfiguration { private final Environment environment;
@Bean public OpenAPI openAPI() { return new OpenAPI() .info(info()); }
private Info info() { return new Info() .title("xxxx") .description(environment.getProperty("spring.application.name") + " 服务 API 文档") .version("xx") .contact(new Contact().name("xxx").url("xxx").email("xxxxx")) .summary("OpenAPI 文档"); } }
|
文档聚合
聚合 swagger 添加分组
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| @Component @AllArgsConstructor public class SwaggerConfig { public static final String MODULE_SUB_PREFIX = "ReactiveCompositeDiscoveryClient_";
private final SwaggerUiConfigParameters swaggerUiConfigParameters;
private final RouteLocator routeLocator;
@Scheduled(fixedDelay = 20000) public void apis() { swaggerUiConfigParameters.getUrls().clear(); routeLocator.getRoutes().subscribe(routeDefinition -> { if (routeDefinition.getId().contains(MODULE_SUB_PREFIX)) { String name = routeDefinition.getId().substring(MODULE_SUB_PREFIX.length()); swaggerUiConfigParameters.addGroup(name); } }); } }
|
修改 /v3/api-docs/ 报文添加 basePath 使得 Knife4j 在聚合文档下能正常调试
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37
| @Component public class AddBasePathFilterFactory extends AbstractGatewayFilterFactory<AddBasePathFilterFactory.Config> {
private final ModifyResponseBodyGatewayFilterFactory modifyResponseBodyGatewayFilterFactory;
public AddBasePathFilterFactory(ModifyResponseBodyGatewayFilterFactory modifyResponseBodyGatewayFilterFactory) { super(Config.class); this.modifyResponseBodyGatewayFilterFactory = modifyResponseBodyGatewayFilterFactory; }
@Override public GatewayFilter apply(Config config) { ModifyResponseBodyGatewayFilterFactory.Config cf = new ModifyResponseBodyGatewayFilterFactory.Config() .setRewriteFunction(JsonNode.class, JsonNode.class, (e, jsonNode) -> Mono.justOrEmpty(addBasePath(e, jsonNode))); return modifyResponseBodyGatewayFilterFactory.apply(cf); }
@Override public String name() { return "AddBasePath"; }
@Setter public static class Config { }
private JsonNode addBasePath(ServerWebExchange exchange, JsonNode jsonNode) { if (jsonNode.isObject()) { ObjectNode node = (ObjectNode) jsonNode; String basePath = exchange.getRequest().getPath().subPath(4).value(); node.put("basePath", basePath); return node; } return jsonNode; } }
|
网关路由配置
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| spring: cloud: gateway: routes: - id: openapi uri: http://localhost:${server.port} predicates: - Path=/v3/api-docs/** filters: - RewritePath=/v3/api-docs/(?<path>.*), /$\{path}/v3/api-docs - AddBasePath - id: doc uri: http://localhost:${server.port} predicates: - Path=/ filters: - RedirectTo=302, /doc.html
|