基于老版本,实现 Spring Cloud Gateway 文档

pull/25/head
YunaiV 2023-03-04 15:40:50 +08:00
parent 59c6963f7c
commit ec280224a8
5 changed files with 165 additions and 199 deletions

View File

@ -57,8 +57,9 @@
</dependency> </dependency>
<dependency> <dependency>
<groupId>org.springdoc</groupId> <groupId>com.github.xiaoymin</groupId> <!-- 接口文档 -->
<artifactId>springdoc-openapi-webflux-ui</artifactId> <artifactId>knife4j-spring-boot-starter</artifactId>
<version>3.0.3</version>
</dependency> </dependency>
<!-- RPC 远程调用相关 --> <!-- RPC 远程调用相关 -->

View File

@ -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;
}
}

View File

@ -1,54 +1,54 @@
//package cn.iocoder.yudao.gateway.swagger; package cn.iocoder.yudao.gateway.swagger;
//
//
//import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
//import org.springframework.http.HttpStatus; import org.springframework.http.HttpStatus;
//import org.springframework.http.ResponseEntity; import org.springframework.http.ResponseEntity;
//import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.GetMapping;
//import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMapping;
//import org.springframework.web.bind.annotation.RestController; import org.springframework.web.bind.annotation.RestController;
//import reactor.core.publisher.Mono; import reactor.core.publisher.Mono;
//import springfox.documentation.swagger.web.*; import springfox.documentation.swagger.web.*;
//
//import javax.annotation.Resource; import javax.annotation.Resource;
//import java.util.List; import java.util.List;
//import java.util.Optional; import java.util.Optional;
//
///** /**
// * Swagger Controller * Swagger Controller
// * *
// * @author zxliu * @author zxliu
// * @date 2022-10-25 11:24 * @date 2022-10-25 11:24
// */ */
//@RestController @RestController
//@RequestMapping("/swagger-resources") @RequestMapping("/swagger-resources")
//public class SwaggerHandler { public class SwaggerHandler {
//
// @Resource @Resource
// private SwaggerResourcesProvider swaggerResources; private SwaggerResourcesProvider swaggerResources;
//
// @SuppressWarnings("SpringJavaAutowiredFieldsWarningInspection") // 只有 @Autowired 可以实现可选注入 @SuppressWarnings("SpringJavaAutowiredFieldsWarningInspection") // 只有 @Autowired 可以实现可选注入
// @Autowired(required = false) @Autowired(required = false)
// private SecurityConfiguration securityConfiguration; private SecurityConfiguration securityConfiguration;
// @SuppressWarnings("SpringJavaAutowiredFieldsWarningInspection") // 只有 @Autowired 可以实现可选注入 @SuppressWarnings("SpringJavaAutowiredFieldsWarningInspection") // 只有 @Autowired 可以实现可选注入
// @Autowired(required = false) @Autowired(required = false)
// private UiConfiguration uiConfiguration; private UiConfiguration uiConfiguration;
//
// @GetMapping("") @GetMapping("")
// public Mono<ResponseEntity<List<SwaggerResource>>> swaggerResources() { public Mono<ResponseEntity<List<SwaggerResource>>> swaggerResources() {
// return Mono.just((new ResponseEntity<>(swaggerResources.get(), HttpStatus.OK))); return Mono.just((new ResponseEntity<>(swaggerResources.get(), HttpStatus.OK)));
// } }
//
// @GetMapping("/configuration/security") @GetMapping("/configuration/security")
// public Mono<ResponseEntity<SecurityConfiguration>> securityConfiguration() { public Mono<ResponseEntity<SecurityConfiguration>> securityConfiguration() {
// return Mono.just(new ResponseEntity<>(Optional.ofNullable(securityConfiguration) return Mono.just(new ResponseEntity<>(Optional.ofNullable(securityConfiguration)
// .orElse(SecurityConfigurationBuilder.builder().build()), HttpStatus.OK)); .orElse(SecurityConfigurationBuilder.builder().build()), HttpStatus.OK));
// } }
//
// @GetMapping("/configuration/ui") @GetMapping("/configuration/ui")
// public Mono<ResponseEntity<UiConfiguration>> uiConfiguration() { public Mono<ResponseEntity<UiConfiguration>> uiConfiguration() {
// return Mono.just(new ResponseEntity<>(Optional.ofNullable(uiConfiguration) return Mono.just(new ResponseEntity<>(Optional.ofNullable(uiConfiguration)
// .orElse(UiConfigurationBuilder.builder().build()), HttpStatus.OK)); .orElse(UiConfigurationBuilder.builder().build()), HttpStatus.OK));
// } }
//
//} }

View File

@ -1,102 +1,102 @@
//package cn.iocoder.yudao.gateway.swagger; package cn.iocoder.yudao.gateway.swagger;
//
//import cn.hutool.core.collection.CollUtil; import cn.hutool.core.collection.CollUtil;
//import cn.hutool.core.util.StrUtil; import cn.hutool.core.util.StrUtil;
//import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
//import org.springframework.cloud.gateway.config.GatewayProperties; import org.springframework.cloud.gateway.config.GatewayProperties;
//import org.springframework.cloud.gateway.handler.predicate.PredicateDefinition; import org.springframework.cloud.gateway.handler.predicate.PredicateDefinition;
//import org.springframework.cloud.gateway.route.RouteDefinition; import org.springframework.cloud.gateway.route.RouteDefinition;
//import org.springframework.cloud.gateway.support.NameUtils; import org.springframework.cloud.gateway.support.NameUtils;
//import org.springframework.context.annotation.Primary; import org.springframework.context.annotation.Primary;
//import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
//import springfox.documentation.swagger.web.SwaggerResource; import springfox.documentation.swagger.web.SwaggerResource;
//import springfox.documentation.swagger.web.SwaggerResourcesProvider; import springfox.documentation.swagger.web.SwaggerResourcesProvider;
//
//import javax.annotation.Resource; import javax.annotation.Resource;
//import java.util.ArrayList; import java.util.ArrayList;
//import java.util.HashSet; import java.util.HashSet;
//import java.util.List; import java.util.List;
//import java.util.Set; import java.util.Set;
//
///** /**
// * Swagger 资源的 Provider 实现类 * Swagger Provider
// * *
// * @author zxliu * @author zxliu
// * @date 2022-10-25 11:23 * @since 2022-10-25 11:23
// */ */
//@Component @Component
//@Primary @Primary
//@Slf4j @Slf4j
//public class SwaggerProvider implements SwaggerResourcesProvider { public class SwaggerProvider implements SwaggerResourcesProvider {
//
// @Resource @Resource
// private GatewayProperties gatewayProperties; private GatewayProperties gatewayProperties;
//
// /** /**
// * 获得 SwaggerResource 列表 * SwaggerResource
// * *
// * @return SwaggerResource 列表 * @return SwaggerResource
// */ */
// @Override @Override
// public List<SwaggerResource> get() { public List<SwaggerResource> get() {
// // 将 RouteDefinition 转换成 SwaggerResource // 将 RouteDefinition 转换成 SwaggerResource
// List<SwaggerResource> resources = new ArrayList<>(); List<SwaggerResource> resources = new ArrayList<>();
// Set<String> serviceNames = new HashSet<>(); // 已处理的服务名,避免重复 Set<String> serviceNames = new HashSet<>(); // 已处理的服务名,避免重复
// gatewayProperties.getRoutes().forEach(route -> { gatewayProperties.getRoutes().forEach(route -> {
// // 已存在的服务,直接忽略 // 已存在的服务,直接忽略
// String serviceName = route.getUri().getHost(); String serviceName = route.getUri().getHost();
// if (StrUtil.isEmpty(serviceName)) { if (StrUtil.isEmpty(serviceName)) {
// return; return;
// } }
// if (!serviceNames.add(serviceName)) { if (!serviceNames.add(serviceName)) {
// return; return;
// } }
//
// // 获得 Path PredicateDefinition // 获得 Path PredicateDefinition
// String path = getRoutePath(route); String path = getRoutePath(route);
// if (path == null) { if (path == null) {
// return; return;
// } }
//
// // 重要:构建最终的 SwaggerResource 对象 // 重要:构建最终的 SwaggerResource 对象
// resources.add(buildSwaggerResource(serviceName, path)); resources.add(buildSwaggerResource(serviceName, path));
// }); });
// return resources; return resources;
// } }
//
// private SwaggerResource buildSwaggerResource(String name, String location) { private SwaggerResource buildSwaggerResource(String name, String location) {
// SwaggerResource swaggerResource = new SwaggerResource(); SwaggerResource swaggerResource = new SwaggerResource();
// swaggerResource.setName(name); swaggerResource.setName(name);
// swaggerResource.setLocation(location); swaggerResource.setLocation(location);
// swaggerResource.setSwaggerVersion("2.0"); swaggerResource.setSwaggerVersion("3.0.3");
// return swaggerResource; return swaggerResource;
// } }
//
// /** /**
// * 获得路由的 Path * Path
// * *
// * ① 输入: *
// * predicates: * predicates:
// * - Path=/admin-api/system/** * - Path=/admin-api/system/**
// * ② 输出: *
// * /admin-api/system/v2/api-docs * /admin-api/system/v3/api-docs
// * *
// * @param route 路由 * @param route
// * @return 路由 * @return
// */ */
// private String getRoutePath(RouteDefinition route) { private String getRoutePath(RouteDefinition route) {
// PredicateDefinition pathDefinition = CollUtil.findOne(route.getPredicates(), PredicateDefinition pathDefinition = CollUtil.findOne(route.getPredicates(),
// predicateDefinition -> "Path".equals(predicateDefinition.getName())); predicateDefinition -> "Path".equals(predicateDefinition.getName()));
// if (pathDefinition == null) { if (pathDefinition == null) {
// log.info("[get][Route({}) 没有 Path 条件,忽略接口文档]", route.getId()); log.info("[get][Route({}) 没有 Path 条件,忽略接口文档]", route.getId());
// return null; return null;
// } }
// String path = pathDefinition.getArgs().get(NameUtils.GENERATED_NAME_PREFIX + "0"); String path = pathDefinition.getArgs().get(NameUtils.GENERATED_NAME_PREFIX + "0");
// if (StrUtil.isEmpty(path)) { if (StrUtil.isEmpty(path)) {
// log.info("[get][Route({}) Path 的值为空,忽略接口文档]", route.getId()); log.info("[get][Route({}) Path 的值为空,忽略接口文档]", route.getId());
// return null; return null;
// } }
// return path.replace("/**", "/v2/api-docs"); return path.replace("/**", "/v3/api-docs");
// } }
//
//} }

View File

@ -12,37 +12,37 @@ spring:
predicates: # 断言,作为路由的匹配条件,对应 RouteDefinition 数组 predicates: # 断言,作为路由的匹配条件,对应 RouteDefinition 数组
- Path=/admin-api/system/** - Path=/admin-api/system/**
filters: 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 # 路由的编号 - id: system-app-api # 路由的编号
uri: grayLb://system-server uri: grayLb://system-server
predicates: # 断言,作为路由的匹配条件,对应 RouteDefinition 数组 predicates: # 断言,作为路由的匹配条件,对应 RouteDefinition 数组
- Path=/app-api/system/** - Path=/app-api/system/**
filters: 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 # 路由的编号 - id: infra-admin-api # 路由的编号
uri: grayLb://infra-server uri: grayLb://infra-server
predicates: # 断言,作为路由的匹配条件,对应 RouteDefinition 数组 predicates: # 断言,作为路由的匹配条件,对应 RouteDefinition 数组
- Path=/admin-api/infra/** - Path=/admin-api/infra/**
filters: 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 # 路由的编号 - id: infra-app-api # 路由的编号
uri: grayLb://infra-server uri: grayLb://infra-server
predicates: # 断言,作为路由的匹配条件,对应 RouteDefinition 数组 predicates: # 断言,作为路由的匹配条件,对应 RouteDefinition 数组
- Path=/app-api/infra/** - Path=/app-api/infra/**
filters: 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 # 路由的编号 - id: bpm-admin-api # 路由的编号
uri: grayLb://bpm-server uri: grayLb://bpm-server
predicates: # 断言,作为路由的匹配条件,对应 RouteDefinition 数组 predicates: # 断言,作为路由的匹配条件,对应 RouteDefinition 数组
- Path=/admin-api/bpm/** - Path=/admin-api/bpm/**
filters: 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 # 路由的编号 - id: report-admin-api # 路由的编号
uri: grayLb://report-server uri: grayLb://report-server
predicates: # 断言,作为路由的匹配条件,对应 RouteDefinition 数组 predicates: # 断言,作为路由的匹配条件,对应 RouteDefinition 数组
- Path=/admin-api/report/** - Path=/admin-api/report/**
filters: filters:
- RewritePath=/admin-api/report/v2/api-docs, /v2/api-docs - RewritePath=/admin-api/report/v3/api-docs, /v3/api-docs
- id: report-jmreport # 路由的编号(积木报表) - id: report-jmreport # 路由的编号(积木报表)
uri: grayLb://report-server uri: grayLb://report-server
predicates: # 断言,作为路由的匹配条件,对应 RouteDefinition 数组 predicates: # 断言,作为路由的匹配条件,对应 RouteDefinition 数组