springcloud-gateway整合Swagger聚合微服务系统API⽂档最近使⽤Spring Cloud Gateway替换Zuul的时候发现Swagger并不⽀持以WebFlux为底层的Gateway,⽆法集成,运⾏报错。
⾸先是⼦项⽬Spring Boot项⽬正常集成Swagger。在业务项⽬Admin中添加Swagger依赖包(使⽤consul为注册中⼼),这⾥跳过。
建⽴⽹关项⽬gateway,添加核⼼依赖包
buildscript {
ext {
springBootVersion = '2.3.8.RELEASE'
}
//...
}
dependencyManagement {
imports {
mavenBom 'org.springframework.cloud:spring-cloud-dependencies:Hoxton.SR10'
}
}
compile 'org.springframework.cloud:spring-cloud-starter-config'
compile 'org.springframework.cloud:spring-cloud-starter-consul-discovery'
compile group: 'org.springframework.cloud', name: 'spring-cloud-starter-gateway'
compile group: 'org.springframework.boot', name: 'spring-boot-starter-webflux'
compile group: 'org.springframework.boot', name: 'spring-boot-autoconfigure'
compile group: 'org.springframework.boot', name: 'spring-boot-starter-logging'
compile group: 'org.springframework.boot', name: 'spring-boot-starter-aop'
compile group: 'org.springframework.boot', name: 'spring-boot-starter-actuator'
compile group: 'org.springframework.boot', name: 'spring-boot-devtools'
annotationProcessor 'org.projectlombok:lombok'
//swagger
implementation 'io.springfox:springfox-swagger2:2.9.2'
implementation 'io.springfox:springfox-swagger-ui:2.9.2'
implementation('com.github.xiaoymin:knife4j-spring-ui:2.0.8')
添加gateway路由配置
spring:
application:
name: gateway # 服务名称
cloud:
consul:
discovery:
hostname: 本机ip
config:
name: ${spring.application.name}
uri: ip:11111
profile: default
label: master
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
因为Swagger暂不⽀持webflux项⽬,所以Gateway⾥不能配置SwaggerConfig,也就是说Gateway⽆法提供⾃⾝API。但我想⼀般也不会在
⽹关项⽬代码⾥写业务API代码吧。所以这⾥的集成只是基于基于WebMvc的微服务项⽬。
配置SwaggerProvider,获取Api-doc,即SwaggerResources。
@Component
@Primary
@AllArgsConstructor
springframework和springbootpublic 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
//结合配置的route-路径(Path),和route过滤,只获取有效的route节点
.forEach(routeDefinition -> Predicates().stream()
.filter(predicateDefinition -> ("Path").Name()))
.forEach(predicateDefinition -> resources.add(Id(),
.replace("/**", 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;
}
}
因为Gateway⾥没有配置SwaggerConfig,⽽运⾏Swagger-ui⼜需要依赖⼀些接⼝,所以我的想法是⾃⼰建⽴相应的swagger-resource端点。
@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<>((), HttpStatus.OK)));
}
}
这时启动Gateway,访问gateway-ip:gateway-port/swagger-ui.html时,即可正常使⽤swagger。
补充⼀下SwaggerHeaderFilter类:
/**
* @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 = Request();
String path = URI().getPath();
if (!dsWithIgnoreCase(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);
};
}
}
参考:
blog.csdn/ttzommed/article/details/81103609?utm_medium=distribute.-task-blog-
2%7Edefault%l&depth_1-utm_source=distribute.-task-blog-2%7Edefault%l
blog.csdn/qq_31748587/article/details/102563155
blog.csdn/lk1822791193/article/details/106540734?utm_medium=distribute.pc_-task-blog-
2~default~ase&depth_1-utm_source=distribute.pc_-task-blog-
2~default~as
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论