From 7bed81873002364cc3f2a2e6f774fdfaf88d6a17 Mon Sep 17 00:00:00 2001 From: xiongxiaoyang <773861846@qq.com> Date: Sat, 3 Apr 2021 20:44:38 +0800 Subject: [PATCH] =?UTF-8?q?=E7=BD=91=E5=85=B3=E9=9B=86=E6=88=90swagger?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- doc/yml/20210403/novel-gateway.yml | 68 +++++++++++++++++++ novel-gateway/pom.xml | 18 +++++ .../novel/gateway/swagger/SwaggerFilter.java | 38 +++++++++++ .../novel/gateway/swagger/SwaggerHandler.java | 48 +++++++++++++ .../gateway/swagger/SwaggerProvider.java | 57 ++++++++++++++++ .../src/main/resources/bootstrap.yml | 7 +- pom.xml | 2 +- 7 files changed, 236 insertions(+), 2 deletions(-) create mode 100644 doc/yml/20210403/novel-gateway.yml create mode 100644 novel-gateway/src/main/java/com/java2nb/novel/gateway/swagger/SwaggerFilter.java create mode 100644 novel-gateway/src/main/java/com/java2nb/novel/gateway/swagger/SwaggerHandler.java create mode 100644 novel-gateway/src/main/java/com/java2nb/novel/gateway/swagger/SwaggerProvider.java diff --git a/doc/yml/20210403/novel-gateway.yml b/doc/yml/20210403/novel-gateway.yml new file mode 100644 index 0000000..28b7350 --- /dev/null +++ b/doc/yml/20210403/novel-gateway.yml @@ -0,0 +1,68 @@ +management: #开启SpringBoot Admin的监控 + endpoints: + web: + exposure: + include: '*' + endpoint: + health: + show-details: always + +server: + port: 527 +spring: + cloud: + nacos: + discovery: + server-addr: 47.106.243.172:8848 + namespace: 3960c71a-62ac-4b8f-8c30-bba8e8143a0c + gateway: + routes: + - id: home-route + uri: lb://novel-home + predicates: + - Path=/api/home/** + filters: + #注意过滤器按顺序执行,下面的顺序不能打乱 + - SwaggerFilter + - RewritePath=/api/(?.*), /$\{segment} + - id: news-route + uri: lb://news-service + predicates: + - Path=/api/news/** + filters: + #注意过滤器按顺序执行,下面的顺序不能打乱 + - SwaggerFilter + - RewritePath=/api/(?.*), /$\{segment} + - id: user-route + uri: lb://user-service + predicates: + - Path=/api/user/** + filters: + #注意过滤器按顺序执行,下面的顺序不能打乱 + - SwaggerFilter + - RewritePath=/api/(?.*), /$\{segment} + - id: book-route + uri: lb://book-service + predicates: + - Path=/api/book/** + filters: + #注意过滤器按顺序执行,下面的顺序不能打乱 + - SwaggerFilter + - RewritePath=/api/(?.*), /$\{segment} + - id: search-route + uri: lb://novel-search + predicates: + - Path=/api/search/** + filters: + #注意过滤器按顺序执行,下面的顺序不能打乱 + - SwaggerFilter + - RewritePath=/api/(?.*), /$\{segment} + - id: monitor-route + uri: lb://novel-monitor + predicates: + - Path=/monitor/** + filters: + - RewritePath=/monitor/(?.*), /$\{segment} + + + \ No newline at end of file diff --git a/novel-gateway/pom.xml b/novel-gateway/pom.xml index 92cd7ba..4e95d9f 100644 --- a/novel-gateway/pom.xml +++ b/novel-gateway/pom.xml @@ -45,6 +45,24 @@ sentinel-transport-simple-http + + + io.springfox + springfox-swagger2 + + + + + io.springfox + springfox-swagger-ui + + + + org.projectlombok + lombok + + + diff --git a/novel-gateway/src/main/java/com/java2nb/novel/gateway/swagger/SwaggerFilter.java b/novel-gateway/src/main/java/com/java2nb/novel/gateway/swagger/SwaggerFilter.java new file mode 100644 index 0000000..97b22e8 --- /dev/null +++ b/novel-gateway/src/main/java/com/java2nb/novel/gateway/swagger/SwaggerFilter.java @@ -0,0 +1,38 @@ +package com.java2nb.novel.gateway.swagger; + +import org.apache.commons.lang3.StringUtils; +import org.springframework.cloud.gateway.filter.GatewayFilter; +import org.springframework.cloud.gateway.filter.factory.AbstractGatewayFilterFactory; +import org.springframework.http.server.reactive.ServerHttpRequest; +import org.springframework.stereotype.Component; +import org.springframework.web.server.ServerWebExchange; +/** + * swagger过滤器,重新设置单个微服务接口文档的路径和接口的基础请求路径 + * 如果要让网关的swagger生效,一定要在每个微服务路由配置的过滤器filters首行配置上SwaggerFilter + * 因为filters下的过滤器按顺序执行,所以一定要注意顺序,只能放到首行 + * @author xiongxiaoyang + * @version 1.0 + * @since 2021/4/3 + */ +@Component +public class SwaggerFilter 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); + } + //重新设置doc文档的路径(断言先执行,不影响已经断言到的服务) + ServerHttpRequest.Builder build = request.mutate().path("/api"+SwaggerProvider.API_URI); + //设置接口的基础请求路径 + ServerHttpRequest newRequest = build.header(HEADER_NAME, "/api").build(); + ServerWebExchange newExchange = exchange.mutate().request(newRequest).build(); + return chain.filter(newExchange); + }; + } +} diff --git a/novel-gateway/src/main/java/com/java2nb/novel/gateway/swagger/SwaggerHandler.java b/novel-gateway/src/main/java/com/java2nb/novel/gateway/swagger/SwaggerHandler.java new file mode 100644 index 0000000..baf8cc6 --- /dev/null +++ b/novel-gateway/src/main/java/com/java2nb/novel/gateway/swagger/SwaggerHandler.java @@ -0,0 +1,48 @@ +package com.java2nb.novel.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.*; + + +/** + * swagger handler + * @author xiongxiaoyang + * @version 1.0 + * @since 2021/4/3 + */ +@RestController +@RequestMapping("/swagger-resources") +public class SwaggerHandler { + + + private final SwaggerResourcesProvider swaggerResources; + + @Autowired + public SwaggerHandler(SwaggerResourcesProvider swaggerResources) { + this.swaggerResources = swaggerResources; + } + + + @GetMapping("/configuration/security") + public Mono> securityConfiguration() { + return Mono.just(new ResponseEntity<>( + SecurityConfigurationBuilder.builder().build(), HttpStatus.OK)); + } + + @GetMapping("/configuration/ui") + public Mono> uiConfiguration() { + return Mono.just(new ResponseEntity<>( + UiConfigurationBuilder.builder().build(), HttpStatus.OK)); + } + + @GetMapping("") + public Mono swaggerResources() { + return Mono.just((new ResponseEntity<>(swaggerResources.get(), HttpStatus.OK))); + } +} diff --git a/novel-gateway/src/main/java/com/java2nb/novel/gateway/swagger/SwaggerProvider.java b/novel-gateway/src/main/java/com/java2nb/novel/gateway/swagger/SwaggerProvider.java new file mode 100644 index 0000000..9e58724 --- /dev/null +++ b/novel-gateway/src/main/java/com/java2nb/novel/gateway/swagger/SwaggerProvider.java @@ -0,0 +1,57 @@ +package com.java2nb.novel.gateway.swagger; + +import lombok.AllArgsConstructor; +import org.springframework.cloud.gateway.config.GatewayProperties; +import org.springframework.cloud.gateway.route.RouteLocator; +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 java.util.ArrayList; +import java.util.List; + +/** + * swagger provider,设置需要由网关管理的微服务资源名和路径 + * @author xiongxiaoyang + * @version 1.0 + * @since 2021/4/3 + */ +@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 get() { + List resources = new ArrayList<>(); + List 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()) && predicateDefinition.getArgs().get(NameUtils.GENERATED_NAME_PREFIX + "0").startsWith("/api/")) + .forEach( + predicateDefinition -> resources.add(swaggerResource(routeDefinition.getId(), + predicateDefinition.getArgs().get(NameUtils.GENERATED_NAME_PREFIX + "0") + .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; + } +} diff --git a/novel-gateway/src/main/resources/bootstrap.yml b/novel-gateway/src/main/resources/bootstrap.yml index c42e031..9e3aaf3 100644 --- a/novel-gateway/src/main/resources/bootstrap.yml +++ b/novel-gateway/src/main/resources/bootstrap.yml @@ -9,6 +9,11 @@ spring: file-extension: yml group: ${spring.application.name} namespace: 3960c71a-62ac-4b8f-8c30-bba8e8143a0c + #关闭Spring自带的X-Forwarded-Prefix设置 + gateway: + x-forwarded: + prefix-enabled: false main: - allow-bean-definition-overriding: true \ No newline at end of file + allow-bean-definition-overriding: true + diff --git a/pom.xml b/pom.xml index 8b42bac..1f6cc64 100644 --- a/pom.xml +++ b/pom.xml @@ -42,7 +42,7 @@ 2.1.0.RELEASE 2.2.0.RELEASE 0.2.2.RELEASE - 2.7.0 + 2.9.2 true 8.0.11 1.3.2