SpringCloudGateway+Discovery+Swagger 动态更新分组API清单
SpringCloudGateway+Discovery+Swagger 搭建服务文档中心
中使用配置方法创建分组API清单,如果服务发生变更,需重启gateway才能生效
解决
修改SwaggerConfig.java
@Configuration
public class SwaggerConfig {
...
// 注入SWAGGER-UI配置参数
@Autowired
SwaggerUiConfigParameters swaggerUiConfigParameters;
...
// 撤销分组API JAVA配置
// @Bean
// public List<GroupedOpenApi> apis() {
// List<GroupedOpenApi> groups = new ArrayList<>();
// List<RouteDefinition> definitions = locator.getRouteDefinitions().collectList().block();
// definitions.stream().forEach(routeDefinition -> {
// String name = routeDefinition.getUri().getHost();
// GroupedOpenApi groupedOpenApi =
// GroupedOpenApi.builder()
// .group(name)
// .pathsToMatch(
// routeDefinition.getPredicates().get(0).getArgs().get("pattern")
// ).build();
// groups.add(groupedOpenApi);
// });
// return groups;
// }
// 定时更新API分组
@Scheduled(fixedDelay = 200)
public void refreshGroupedApi() {
List<RouteDefinition> definitions = locator.getRouteDefinitions().collectList().block();
swaggerUiConfigParameters.getUrls().clear();
definitions.stream().forEach(routeDefinition -> {
String name = routeDefinition.getUri().getHost();
swaggerUiConfigParameters.addGroup(name);
});
}
}
源码分析
SWAGGER-UI获取配置信息的端点
org.springdoc.webflux.ui.SwaggerWelcomeActuator
@ControllerEndpoint(
id = "swaggerui"
)
public class SwaggerWelcomeActuator extends SwaggerWelcomeCommon {
@GetMapping(
value = {"/swagger-config"},
produces = {"application/json"}
)
@ResponseBody
public Map<String, Object> getSwaggerUiConfig(ServerHttpRequest request) {
return super.getSwaggerUiConfig(request);
}
}
org.springdoc.webflux.ui.AbstractSwaggerWelcome
public abstract class SwaggerWelcomeCommon extends AbstractSwaggerWelcome {
// 构造时注入swaggerUiConfigParameters
public AbstractSwaggerWelcome(SwaggerUiConfigProperties swaggerUiConfig, SpringDocConfigProperties springDocConfigProperties, SwaggerUiConfigParameters swaggerUiConfigParameters) {
this.swaggerUiConfig = swaggerUiConfig;
this.springDocConfigProperties = springDocConfigProperties;
this.swaggerUiConfigParameters = swaggerUiConfigParameters;
}
// 这里会根据分组API配置来创建UI需要使用的分组下拉清单数据
@Override
public void afterPropertiesSet() {
springDocConfigProperties.getGroupConfigs().forEach(groupConfig -> swaggerUiConfigParameters.addGroup(groupConfig.getGroup()));
calculateUiRootPath();
}
protected Map<String, Object> getSwaggerUiConfig(ServerHttpRequest request) {
this.buildFromCurrentContextPath(request);
return swaggerUiConfigParameters.getConfigParameters();
}
private void buildFromCurrentContextPath(ServerHttpRequest request) {
contextPath = request.getPath().contextPath().value();
String url = UriComponentsBuilder.fromHttpRequest(request).toUriString();
if (!AntPathMatcher.DEFAULT_PATH_SEPARATOR.equals(request.getPath().toString()))
url = url.replace(request.getPath().toString(), "");
buildConfigUrl(UriComponentsBuilder.fromUriString(url));
}
}
org.springdoc.webflux.ui.AbstractSwaggerWelcome
public abstract class AbstractSwaggerWelcome implements InitializingBean {
protected void buildConfigUrl(UriComponentsBuilder uriComponentsBuilder) {
if (StringUtils.isEmpty(swaggerUiConfig.getConfigUrl())) {
apiDocsUrl = buildApiDocUrl();
swaggerConfigUrl = buildSwaggerConfigUrl(); // 默认值为 /v3/api-docs
swaggerUiConfigParameters.setConfigUrl(swaggerConfigUrl);
if (CollectionUtils.isEmpty(swaggerUiConfigParameters.getUrls())) {
String swaggerUiUrl = swaggerUiConfig.getUrl();
if (StringUtils.isEmpty(swaggerUiUrl))
swaggerUiConfigParameters.setUrl(apiDocsUrl);
else
swaggerUiConfigParameters.setUrl(swaggerUiUrl); // 这一步会给每个api分组的配置url初始化赋值 /v3/api-docs/groupedApiName
}
else
swaggerUiConfigParameters.addUrl(apiDocsUrl);
}
calculateOauth2RedirectUrl(uriComponentsBuilder);
}
}
org.springdoc.core.SwaggerUiConfigParameters
public class SwaggerUiConfigParameters extends AbstractSwaggerUiConfigProperties {
public void addUrl(String url) {
this.urls.forEach(elt ->
{
if (!isSwaggerUrlDefined(elt.getName()))
elt.setUrl(url + DEFAULT_PATH_SEPARATOR + elt.getName());
}
);
}
}