- test 服務中已配置分組
- 配置網關
- pom 添加依賴
<dependency> <groupId>io.springfox</groupId> <artifactId>springfox-swagger2</artifactId> <version>2.9.2</version> <scope>compile</scope> </dependency> <dependency> <groupId>io.springfox</groupId> <artifactId>springfox-swagger-ui</artifactId> <version>2.9.2</version> </dependency>
- 注入路由到 SwaggerResource
@Component @Primary public class SwaggerProvider implements SwaggerResourcesProvider { public static final String API_URI = "/v2/api-docs"; private RouteLocator routeLocator; private 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 -> { // FIXME 能力有限想不出更好的實現方法來整合單個服務的分組問題 String name = routeDefinition.getId(); // name爲服務名 if ("test".equals(name)) { String location = predicateDefinition.getArgs().get(NameUtils.GENERATED_NAME_PREFIX + "0") .replace("/**", API_URI); resources.add(swaggerResource(name + "/test1", location + "?group=test1")); resources.add(swaggerResource(name + "/test2", location + "?group=test2")); return; } resources.add(swaggerResource(name, 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; } @Autowired public SwaggerProvider(RouteLocator routeLocator, GatewayProperties gatewayProperties) { this.routeLocator = routeLocator; this.gatewayProperties = gatewayProperties; }
- 提供 Swagger 對外接口
@RestController @RequestMapping("/swagger-resources") public class SwaggerController { @Autowired(required = false) private SecurityConfiguration securityConfiguration; @Autowired(required = false) private UiConfiguration uiConfiguration; private final SwaggerResourcesProvider 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))); } @Autowired public SwaggerController(SwaggerResourcesProvider swaggerResources) { this.swaggerResources = swaggerResources; } }
- Swagger 路徑轉換
通過以上配置,可以實現文檔的參考和展示了,但是使用 Swagger 的 try it out 功能發現路徑是路由切割後的路徑比如:
Swagger 文檔中的路徑爲:
主機名:端口:映射路徑 少了一個 服務路由前綴,是因爲展示 handler 經過了 StripPrefixGatewayFilterFactory 這個過濾器的處理,原有的 路由前綴被過濾掉了!- 方案1:通過 Swagger 的 host 配置手動維護一個前綴
return new Docket(DocumentationType.SWAGGER_2) .apiInfo(apiInfo()) .host("主機名:端口:服務前綴") //注意這裏的主機名:端口是網關的地址和端口 .select() .apis(RequestHandlerSelectors.withMethodAnnotation(ApiOperation.class)) .paths(PathSelectors.any()) .build() .globalOperationParameters(parameterList);
- 方案2:增加 X-Forwarded-Prefix
配置 appction.yml@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); }; } }
- id: test uri: lb://test predicates: - Path=/test/** filters: - SwaggerHeaderFilter - StripPrefix=1
- 方案1:通過 Swagger 的 host 配置手動維護一個前綴
- pom 添加依賴
- Nginx 配置
- Nginx 配置文件
# 配置使用用戶名和密碼登錄 location /swagger-ui.html { auth_basic "test"; # 相對路徑:htpasswd在機器上的位置:/usr/local/nginx/conf/htpasswd auth_basic_user_file htpasswd; # 絕對路徑:htpasswd在機器上的位置:/tmp/htpasswd # auth_basic_user_file /tmp/htpasswd; proxy_pass http://zxjl/swagger-ui.html; } location /swagger-resources { proxy_pass http://zxjl/swagger-resources; } location /webjars { proxy_pass http://zxjl/webjars; }
- 創建 htpasswd
# 格式:用戶名:密碼,注意密碼是使用crypt加密過的 admin:PbSRr7orsxaso
- Nginx 配置文件
參考:Spring Cloud Gateway 聚合swagger文檔
nginx配置指令auth_basic、auth_basic_user_file及相關知識