pom
gateway项目的依赖
本着依赖整洁的原则,我加的是这些:
<!--swagger-->
<dependency>
<groupId>com.spring4all</groupId>
<artifactId>swagger-spring-boot-starter</artifactId>
<version>1.9.1.RELEASE</version>
</dependency>
<!-- 注册中心的依赖 -->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
<!-- 网关依赖 - 此处不能加 spring boot web 依赖,会报错-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-gateway</artifactId>
</dependency>
被代理的服务需要的操作:
在启动类上加上 @EnableSwagger2
这个注解
然后也引入下边的依赖:
<!--swagger-->
<dependency>
<groupId>com.spring4all</groupId>
<artifactId>swagger-spring-boot-starter</artifactId>
<version>1.9.1.RELEASE</version>
</dependency>
配置类
这里是重头戏,一共有三个配置类
/**
* @introduce: Swagger处理器
* @author: lk
* @date: 2020/6/4
**/
@RestController
@RequestMapping("/swagger-resources")
public class SwaggerHandler {
@Autowired(required = false)
private SecurityConfiguration securityConfiguration;
@Autowired(required = false)
private UiConfiguration uiConfiguration;
private final SwaggerResourcesProvider swaggerResources;
@Autowired
public SwaggerHandler(SwaggerResourcesProvider swaggerResources) {
this.swaggerResources = swaggerResources;
}
@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));
}
@GetMapping("")
public Mono<ResponseEntity> swaggerResources() {
return Mono.just((new ResponseEntity<>(swaggerResources.get(), HttpStatus.OK)));
}
}
/**
* @introduce: swagger请求头过滤器
* @author: lk
* @date: 2020/6/4
**/
@Component
public class SwaggerHeaderFilter extends AbstractGatewayFilterFactory {
private static final String HEADER_NAME = "X-Forwarded-Prefix";
@Override
public GatewayFilter apply(Object config) {
return (exchange, chain) -> {
ServerHttpRequest request = exchange.getRequest();
String path = request.getURI().getPath();
if (!StringUtils.endsWithIgnoreCase(path, SwaggerProvider.API_URI)) {
return chain.filter(exchange);
}
String basePath = path.substring(0, path.lastIndexOf(SwaggerProvider.API_URI));
ServerHttpRequest newRequest = request.mutate().header(HEADER_NAME, basePath).build();
ServerWebExchange newExchange = exchange.mutate().request(newRequest).build();
return chain.filter(newExchange);
};
}
}
/**
* @introduce: SwaggerProvider
* @author: lk
* @date: 2020/6/4
**/
@Component
@Primary
@AllArgsConstructor
public class SwaggerProvider implements SwaggerResourcesProvider {
public static final String API_URI = "/v2/api-docs";
private final RouteLocator routeLocator;
private final GatewayProperties gatewayProperties;
@Override
public List<SwaggerResource> get() {
List<SwaggerResource> resources = new ArrayList<>();
List<String> routes = new ArrayList<>();
//取出gateway的route
routeLocator.getRoutes().subscribe(route -> routes.add(route.getId()));
//结合配置的route-路径(Path),和route过滤,只获取有效的route节点
gatewayProperties.getRoutes().stream().filter(routeDefinition -> routes.contains(routeDefinition.getId()))
.forEach(routeDefinition -> routeDefinition.getPredicates().stream()
.filter(predicateDefinition -> ("Path").equalsIgnoreCase(predicateDefinition.getName()))
.forEach(predicateDefinition -> resources.add(swaggerResource(routeDefinition.getId(),
"/"+routeDefinition.getId()+API_URI ))));
return resources;
}
private SwaggerResource swaggerResource(String name, String location) {
SwaggerResource swaggerResource = new SwaggerResource();
swaggerResource.setName(name);
swaggerResource.setLocation(location);
swaggerResource.setSwaggerVersion("2.0");
return swaggerResource;
}
}
yml
spring:
application:
name: gateway # 服务名称
cloud:
nacos:
discovery:
server-addr: localhost:8848 # 注册中心地址 # 默认是没有密码的
gateway:
discovery:
locator:
enabled: true #表明gateway开启服务注册和发现的功能, 动态路由
lowerCaseServiceId: true
filters:
routes:
- id: test # 唯一id ,随便起,不能重复
uri: lb://test # 匹配注册中心的服务
predicates:
- Path=/test/** # 匹配的规则
filters:
# 去掉路由前缀,访问 localhost:8088/test/v2/api 转发的就是 localhost:8089/v2/api
# 1 : 代表剥离路径的个数
- StripPrefix=1
特别注意:
filters:
-StripPrefix=1
这个一定不要去掉,不然你就访问不到你服务的swagger,如下图
结果
这样配置一下以后,就可以成功的通过 gateway 的地址访问 各个微服务的swagger了,如下图:
巨人的肩膀:
1、全网首例Spring Cloud Gateway整合Swagger2 Demo
2、springcloud-gateway网关聚合swagger实现多个服务接口切换
3、spring cloud gateway聚合swagger的方法记录
看似简单,实则鼓捣了半天,亲测没问题,如果大家遇到了什么问题,欢迎评论提出,我们一起讨论!