基于老版本,实现 Spring Cloud Gateway 文档
parent
59c6963f7c
commit
ec280224a8
|
@ -57,8 +57,9 @@
|
|||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.springdoc</groupId>
|
||||
<artifactId>springdoc-openapi-webflux-ui</artifactId>
|
||||
<groupId>com.github.xiaoymin</groupId> <!-- 接口文档 -->
|
||||
<artifactId>knife4j-spring-boot-starter</artifactId>
|
||||
<version>3.0.3</version>
|
||||
</dependency>
|
||||
|
||||
<!-- RPC 远程调用相关 -->
|
||||
|
|
|
@ -1,35 +0,0 @@
|
|||
package cn.iocoder.yudao.gateway.config;
|
||||
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springdoc.core.GroupedOpenApi;
|
||||
import org.springframework.cloud.gateway.route.RouteDefinition;
|
||||
import org.springframework.cloud.gateway.route.RouteDefinitionLocator;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.context.annotation.Lazy;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
@Slf4j
|
||||
@Configuration
|
||||
public class SpringDocConfiguration {
|
||||
private static final String SERVER_NAME_SUFFIX = "-api";
|
||||
|
||||
@Bean
|
||||
@Lazy(false)
|
||||
public List<GroupedOpenApi> apis(RouteDefinitionLocator locator) {
|
||||
List<GroupedOpenApi> groups = new ArrayList<>();
|
||||
List<RouteDefinition> definitions = locator.getRouteDefinitions().collectList().block();
|
||||
for (RouteDefinition definition : definitions) {
|
||||
log.info("id: " + definition.getId() + " " + definition.getUri().toString());
|
||||
}
|
||||
definitions.stream()
|
||||
.filter(routeDefinition -> routeDefinition.getId().matches(".*"+SERVER_NAME_SUFFIX))
|
||||
.forEach(routeDefinition -> {
|
||||
String name = routeDefinition.getId().replaceAll(SERVER_NAME_SUFFIX, "");
|
||||
GroupedOpenApi.builder().pathsToMatch("/" + name + "/**").group(name).build();
|
||||
});
|
||||
return groups;
|
||||
}
|
||||
}
|
|
@ -1,54 +1,54 @@
|
|||
//package cn.iocoder.yudao.gateway.swagger;
|
||||
//
|
||||
//
|
||||
//import org.springframework.beans.factory.annotation.Autowired;
|
||||
//import org.springframework.http.HttpStatus;
|
||||
//import org.springframework.http.ResponseEntity;
|
||||
//import org.springframework.web.bind.annotation.GetMapping;
|
||||
//import org.springframework.web.bind.annotation.RequestMapping;
|
||||
//import org.springframework.web.bind.annotation.RestController;
|
||||
//import reactor.core.publisher.Mono;
|
||||
//import springfox.documentation.swagger.web.*;
|
||||
//
|
||||
//import javax.annotation.Resource;
|
||||
//import java.util.List;
|
||||
//import java.util.Optional;
|
||||
//
|
||||
///**
|
||||
// * Swagger Controller
|
||||
// *
|
||||
// * @author zxliu
|
||||
// * @date 2022-10-25 11:24
|
||||
// */
|
||||
//@RestController
|
||||
//@RequestMapping("/swagger-resources")
|
||||
//public class SwaggerHandler {
|
||||
//
|
||||
// @Resource
|
||||
// private SwaggerResourcesProvider swaggerResources;
|
||||
//
|
||||
// @SuppressWarnings("SpringJavaAutowiredFieldsWarningInspection") // 只有 @Autowired 可以实现可选注入
|
||||
// @Autowired(required = false)
|
||||
// private SecurityConfiguration securityConfiguration;
|
||||
// @SuppressWarnings("SpringJavaAutowiredFieldsWarningInspection") // 只有 @Autowired 可以实现可选注入
|
||||
// @Autowired(required = false)
|
||||
// private UiConfiguration uiConfiguration;
|
||||
//
|
||||
// @GetMapping("")
|
||||
// public Mono<ResponseEntity<List<SwaggerResource>>> swaggerResources() {
|
||||
// return Mono.just((new ResponseEntity<>(swaggerResources.get(), HttpStatus.OK)));
|
||||
// }
|
||||
//
|
||||
// @GetMapping("/configuration/security")
|
||||
// public Mono<ResponseEntity<SecurityConfiguration>> securityConfiguration() {
|
||||
// return Mono.just(new ResponseEntity<>(Optional.ofNullable(securityConfiguration)
|
||||
// .orElse(SecurityConfigurationBuilder.builder().build()), HttpStatus.OK));
|
||||
// }
|
||||
//
|
||||
// @GetMapping("/configuration/ui")
|
||||
// public Mono<ResponseEntity<UiConfiguration>> uiConfiguration() {
|
||||
// return Mono.just(new ResponseEntity<>(Optional.ofNullable(uiConfiguration)
|
||||
// .orElse(UiConfigurationBuilder.builder().build()), HttpStatus.OK));
|
||||
// }
|
||||
//
|
||||
//}
|
||||
package cn.iocoder.yudao.gateway.swagger;
|
||||
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
import reactor.core.publisher.Mono;
|
||||
import springfox.documentation.swagger.web.*;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
|
||||
/**
|
||||
* Swagger Controller
|
||||
*
|
||||
* @author zxliu
|
||||
* @date 2022-10-25 11:24
|
||||
*/
|
||||
@RestController
|
||||
@RequestMapping("/swagger-resources")
|
||||
public class SwaggerHandler {
|
||||
|
||||
@Resource
|
||||
private SwaggerResourcesProvider swaggerResources;
|
||||
|
||||
@SuppressWarnings("SpringJavaAutowiredFieldsWarningInspection") // 只有 @Autowired 可以实现可选注入
|
||||
@Autowired(required = false)
|
||||
private SecurityConfiguration securityConfiguration;
|
||||
@SuppressWarnings("SpringJavaAutowiredFieldsWarningInspection") // 只有 @Autowired 可以实现可选注入
|
||||
@Autowired(required = false)
|
||||
private UiConfiguration uiConfiguration;
|
||||
|
||||
@GetMapping("")
|
||||
public Mono<ResponseEntity<List<SwaggerResource>>> swaggerResources() {
|
||||
return Mono.just((new ResponseEntity<>(swaggerResources.get(), HttpStatus.OK)));
|
||||
}
|
||||
|
||||
@GetMapping("/configuration/security")
|
||||
public Mono<ResponseEntity<SecurityConfiguration>> securityConfiguration() {
|
||||
return Mono.just(new ResponseEntity<>(Optional.ofNullable(securityConfiguration)
|
||||
.orElse(SecurityConfigurationBuilder.builder().build()), HttpStatus.OK));
|
||||
}
|
||||
|
||||
@GetMapping("/configuration/ui")
|
||||
public Mono<ResponseEntity<UiConfiguration>> uiConfiguration() {
|
||||
return Mono.just(new ResponseEntity<>(Optional.ofNullable(uiConfiguration)
|
||||
.orElse(UiConfigurationBuilder.builder().build()), HttpStatus.OK));
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -1,102 +1,102 @@
|
|||
//package cn.iocoder.yudao.gateway.swagger;
|
||||
//
|
||||
//import cn.hutool.core.collection.CollUtil;
|
||||
//import cn.hutool.core.util.StrUtil;
|
||||
//import lombok.extern.slf4j.Slf4j;
|
||||
//import org.springframework.cloud.gateway.config.GatewayProperties;
|
||||
//import org.springframework.cloud.gateway.handler.predicate.PredicateDefinition;
|
||||
//import org.springframework.cloud.gateway.route.RouteDefinition;
|
||||
//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 javax.annotation.Resource;
|
||||
//import java.util.ArrayList;
|
||||
//import java.util.HashSet;
|
||||
//import java.util.List;
|
||||
//import java.util.Set;
|
||||
//
|
||||
///**
|
||||
// * Swagger 资源的 Provider 实现类
|
||||
// *
|
||||
// * @author zxliu
|
||||
// * @date 2022-10-25 11:23
|
||||
// */
|
||||
//@Component
|
||||
//@Primary
|
||||
//@Slf4j
|
||||
//public class SwaggerProvider implements SwaggerResourcesProvider {
|
||||
//
|
||||
// @Resource
|
||||
// private GatewayProperties gatewayProperties;
|
||||
//
|
||||
// /**
|
||||
// * 获得 SwaggerResource 列表
|
||||
// *
|
||||
// * @return SwaggerResource 列表
|
||||
// */
|
||||
// @Override
|
||||
// public List<SwaggerResource> get() {
|
||||
// // 将 RouteDefinition 转换成 SwaggerResource
|
||||
// List<SwaggerResource> resources = new ArrayList<>();
|
||||
// Set<String> serviceNames = new HashSet<>(); // 已处理的服务名,避免重复
|
||||
// gatewayProperties.getRoutes().forEach(route -> {
|
||||
// // 已存在的服务,直接忽略
|
||||
// String serviceName = route.getUri().getHost();
|
||||
// if (StrUtil.isEmpty(serviceName)) {
|
||||
// return;
|
||||
// }
|
||||
// if (!serviceNames.add(serviceName)) {
|
||||
// return;
|
||||
// }
|
||||
//
|
||||
// // 获得 Path PredicateDefinition
|
||||
// String path = getRoutePath(route);
|
||||
// if (path == null) {
|
||||
// return;
|
||||
// }
|
||||
//
|
||||
// // 重要:构建最终的 SwaggerResource 对象
|
||||
// resources.add(buildSwaggerResource(serviceName, path));
|
||||
// });
|
||||
// return resources;
|
||||
// }
|
||||
//
|
||||
// private SwaggerResource buildSwaggerResource(String name, String location) {
|
||||
// SwaggerResource swaggerResource = new SwaggerResource();
|
||||
// swaggerResource.setName(name);
|
||||
// swaggerResource.setLocation(location);
|
||||
// swaggerResource.setSwaggerVersion("2.0");
|
||||
// return swaggerResource;
|
||||
// }
|
||||
//
|
||||
// /**
|
||||
// * 获得路由的 Path
|
||||
// *
|
||||
// * ① 输入:
|
||||
// * predicates:
|
||||
// * - Path=/admin-api/system/**
|
||||
// * ② 输出:
|
||||
// * /admin-api/system/v2/api-docs
|
||||
// *
|
||||
// * @param route 路由
|
||||
// * @return 路由
|
||||
// */
|
||||
// private String getRoutePath(RouteDefinition route) {
|
||||
// PredicateDefinition pathDefinition = CollUtil.findOne(route.getPredicates(),
|
||||
// predicateDefinition -> "Path".equals(predicateDefinition.getName()));
|
||||
// if (pathDefinition == null) {
|
||||
// log.info("[get][Route({}) 没有 Path 条件,忽略接口文档]", route.getId());
|
||||
// return null;
|
||||
// }
|
||||
// String path = pathDefinition.getArgs().get(NameUtils.GENERATED_NAME_PREFIX + "0");
|
||||
// if (StrUtil.isEmpty(path)) {
|
||||
// log.info("[get][Route({}) Path 的值为空,忽略接口文档]", route.getId());
|
||||
// return null;
|
||||
// }
|
||||
// return path.replace("/**", "/v2/api-docs");
|
||||
// }
|
||||
//
|
||||
//}
|
||||
package cn.iocoder.yudao.gateway.swagger;
|
||||
|
||||
import cn.hutool.core.collection.CollUtil;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.cloud.gateway.config.GatewayProperties;
|
||||
import org.springframework.cloud.gateway.handler.predicate.PredicateDefinition;
|
||||
import org.springframework.cloud.gateway.route.RouteDefinition;
|
||||
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 javax.annotation.Resource;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* Swagger 资源的 Provider 实现类
|
||||
*
|
||||
* @author zxliu
|
||||
* @since 2022-10-25 11:23
|
||||
*/
|
||||
@Component
|
||||
@Primary
|
||||
@Slf4j
|
||||
public class SwaggerProvider implements SwaggerResourcesProvider {
|
||||
|
||||
@Resource
|
||||
private GatewayProperties gatewayProperties;
|
||||
|
||||
/**
|
||||
* 获得 SwaggerResource 列表
|
||||
*
|
||||
* @return SwaggerResource 列表
|
||||
*/
|
||||
@Override
|
||||
public List<SwaggerResource> get() {
|
||||
// 将 RouteDefinition 转换成 SwaggerResource
|
||||
List<SwaggerResource> resources = new ArrayList<>();
|
||||
Set<String> serviceNames = new HashSet<>(); // 已处理的服务名,避免重复
|
||||
gatewayProperties.getRoutes().forEach(route -> {
|
||||
// 已存在的服务,直接忽略
|
||||
String serviceName = route.getUri().getHost();
|
||||
if (StrUtil.isEmpty(serviceName)) {
|
||||
return;
|
||||
}
|
||||
if (!serviceNames.add(serviceName)) {
|
||||
return;
|
||||
}
|
||||
|
||||
// 获得 Path PredicateDefinition
|
||||
String path = getRoutePath(route);
|
||||
if (path == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
// 重要:构建最终的 SwaggerResource 对象
|
||||
resources.add(buildSwaggerResource(serviceName, path));
|
||||
});
|
||||
return resources;
|
||||
}
|
||||
|
||||
private SwaggerResource buildSwaggerResource(String name, String location) {
|
||||
SwaggerResource swaggerResource = new SwaggerResource();
|
||||
swaggerResource.setName(name);
|
||||
swaggerResource.setLocation(location);
|
||||
swaggerResource.setSwaggerVersion("3.0.3");
|
||||
return swaggerResource;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获得路由的 Path
|
||||
*
|
||||
* ① 输入:
|
||||
* predicates:
|
||||
* - Path=/admin-api/system/**
|
||||
* ② 输出:
|
||||
* /admin-api/system/v3/api-docs
|
||||
*
|
||||
* @param route 路由
|
||||
* @return 路由
|
||||
*/
|
||||
private String getRoutePath(RouteDefinition route) {
|
||||
PredicateDefinition pathDefinition = CollUtil.findOne(route.getPredicates(),
|
||||
predicateDefinition -> "Path".equals(predicateDefinition.getName()));
|
||||
if (pathDefinition == null) {
|
||||
log.info("[get][Route({}) 没有 Path 条件,忽略接口文档]", route.getId());
|
||||
return null;
|
||||
}
|
||||
String path = pathDefinition.getArgs().get(NameUtils.GENERATED_NAME_PREFIX + "0");
|
||||
if (StrUtil.isEmpty(path)) {
|
||||
log.info("[get][Route({}) Path 的值为空,忽略接口文档]", route.getId());
|
||||
return null;
|
||||
}
|
||||
return path.replace("/**", "/v3/api-docs");
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -12,37 +12,37 @@ spring:
|
|||
predicates: # 断言,作为路由的匹配条件,对应 RouteDefinition 数组
|
||||
- Path=/admin-api/system/**
|
||||
filters:
|
||||
- RewritePath=/admin-api/system/v2/api-docs, /v2/api-docs # 配置,保证转发到 /v2/api-docs
|
||||
- RewritePath=/admin-api/system/v3/api-docs, /v3/api-docs # 配置,保证转发到 /v3/api-docs
|
||||
- id: system-app-api # 路由的编号
|
||||
uri: grayLb://system-server
|
||||
predicates: # 断言,作为路由的匹配条件,对应 RouteDefinition 数组
|
||||
- Path=/app-api/system/**
|
||||
filters:
|
||||
- RewritePath=/app-api/system/v2/api-docs, /v2/api-docs
|
||||
- RewritePath=/app-api/system/v3/api-docs, /v3/api-docs
|
||||
- id: infra-admin-api # 路由的编号
|
||||
uri: grayLb://infra-server
|
||||
predicates: # 断言,作为路由的匹配条件,对应 RouteDefinition 数组
|
||||
- Path=/admin-api/infra/**
|
||||
filters:
|
||||
- RewritePath=/admin-api/infra/v2/api-docs, /v2/api-docs
|
||||
- RewritePath=/admin-api/infra/v3/api-docs, /v3/api-docs
|
||||
- id: infra-app-api # 路由的编号
|
||||
uri: grayLb://infra-server
|
||||
predicates: # 断言,作为路由的匹配条件,对应 RouteDefinition 数组
|
||||
- Path=/app-api/infra/**
|
||||
filters:
|
||||
- RewritePath=/app-api/infra/v2/api-docs, /v2/api-docs
|
||||
- RewritePath=/app-api/infra/v3/api-docs, /v3/api-docs
|
||||
- id: bpm-admin-api # 路由的编号
|
||||
uri: grayLb://bpm-server
|
||||
predicates: # 断言,作为路由的匹配条件,对应 RouteDefinition 数组
|
||||
- Path=/admin-api/bpm/**
|
||||
filters:
|
||||
- RewritePath=/admin-api/bpm/v2/api-docs, /v2/api-docs
|
||||
- RewritePath=/admin-api/bpm/v3/api-docs, /v3/api-docs
|
||||
- id: report-admin-api # 路由的编号
|
||||
uri: grayLb://report-server
|
||||
predicates: # 断言,作为路由的匹配条件,对应 RouteDefinition 数组
|
||||
- Path=/admin-api/report/**
|
||||
filters:
|
||||
- RewritePath=/admin-api/report/v2/api-docs, /v2/api-docs
|
||||
- RewritePath=/admin-api/report/v3/api-docs, /v3/api-docs
|
||||
- id: report-jmreport # 路由的编号(积木报表)
|
||||
uri: grayLb://report-server
|
||||
predicates: # 断言,作为路由的匹配条件,对应 RouteDefinition 数组
|
||||
|
|
Loading…
Reference in New Issue