SpringBoot3.x SpringCloudGateway与SpringDoc OpenApi整合
网关的配置文件
这个是用来转发各个服务的 /v3/api-docs 请求
routes: # 转发swagger接口 - id: openapi uri: http://localhost:${server.port} predicates: - Path=/service/v3/api-docs/** filters: - RewritePath=/service/v3/api-docs/(?<path>.*), /$\{path}/v3/api-docs
网关的swagger配置,去掉前缀,就可以直接用 ip:port/swagger-ui/index.html 访问了
springdoc: swagger-ui: # 禁止默认路径 disable-swagger-default-url: true webjars: # 设置为空,不要前缀 prefix:
Swagger配置类
@Configuration public class SwaggerConfig { @Value(value = "${server.port:8080}") private int port; @Bean public OpenAPI springShopOpenApi() { final String loginToken = "BearerAuth"; return new OpenAPI().info(new Info().title("API") .description("Sky网关") .version("v1.0.0")).externalDocs(new ExternalDocumentation() .description("Sky网关") .url("http://127.0.0.1:" + port)) .components(new Components().addSecuritySchemes(loginToken, new SecurityScheme() .type(SecurityScheme.Type.HTTP).scheme("Bearer").bearerFormat("JWT") .in(SecurityScheme.In.HEADER) .name(loginToken))) .addSecurityItem(new SecurityRequirement().addList(loginToken)); } @Bean public GroupedOpenApi service2Api() { String[] paths = {"/_default/**"}; return GroupedOpenApi.builder().group("_default") .pathsToMatch(paths) .build(); } }
动态刷新Swagger下拉
@Component
public class InstancesChangeEventListener extends Subscriber<InstancesChangeEvent> implements InitializingBean {
private static final Logger logger = LoggerFactory.getLogger(InstancesChangeEventListener.class);
@Autowired
private RouteLocator routeLocator;
@Autowired
private SwaggerUiConfigProperties swaggerUiConfigProperties;
@Value("${spring.application.name}")
private String applicationName;
private Set<AbstractSwaggerUiConfigProperties.SwaggerUrl> urls;
@PostConstruct
private void post() {
NotifyCenter.registerSubscriber(this);
}
/**
* Event callback.
*
* @param event {@link Event}
*/
@Override
public void onEvent(InstancesChangeEvent event) {
logger.info("接收到 InstancesChangeEvent 订阅事件:{}", JSON.toJSONString(event));
CachingRouteLocator cachingRouteLocator = (CachingRouteLocator) routeLocator;
cachingRouteLocator.refresh();
List<Route> routeList = routeLocator.getRoutes().collectList().block();
System.out.println(routeList);
LinkedHashSet<AbstractSwaggerUiConfigProperties.SwaggerUrl> set = new LinkedHashSet<>();
if (CollectionUtils.isNotEmpty(this.urls)) {
set.addAll(this.urls);
}
for (Route route : routeList) {
if (route.getMetadata().size() > 0) {
// ReactiveCompositeDiscoveryClient_sky-user
String id = route.getId();
String name = id.replaceAll("ReactiveCompositeDiscoveryClient_", "");
if (applicationName.equals(name)) {
continue;
}
set.add(new AbstractSwaggerUiConfigProperties.SwaggerUrl(name, "/service/v3/api-docs/" + name, ""));
}
}
if (CollectionUtils.isEmpty(set)) {
set.add(new AbstractSwaggerUiConfigProperties.SwaggerUrl("_default", "/v3/api-docs/_default", ""));
}
swaggerUiConfigProperties.setUrls(set);
}
/**
* Type of this subscriber's subscription.
*
* @return Class which extends {@link Event}
*/
@Override
public Class<? extends com.alibaba.nacos.common.notify.Event> subscribeType() {
return InstancesChangeEvent.class;
}
@Override
public void afterPropertiesSet() throws Exception {
this.urls = this.swaggerUiConfigProperties.getUrls();
}
}
当没有服务注册在线时,就显示_default这个分组,也避免了报错
作者:Se7end
声明:本博客文章为原创,只代表本人在工作学习中某一时间内总结的观点或结论。转载时请在文章页面明显位置给出原文链接。