Spring Cloud Gateway 整合Swagger2 (微服务API文档)
前提是spring-boot-starter-parent版本为2.1.3.RELEASE
1.创建Gateway module项目,添加maven依赖
<!--gateway 网关依赖,内置webflux 依赖-->
<dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-gateway</artifactId><exclusions><exclusion><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></exclusion></exclusions>
</dependency>
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-redis-reactive</artifactId>
</dependency>
<dependency><groupId>io.springfox</groupId><artifactId>springfox-swagger-ui</artifactId><version>2.9.2</version>
</dependency>
<dependency><groupId>io.springfox</groupId><artifactId>springfox-swagger2</artifactId><version>2.9.2</version>
</dependency>
<dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-gateway-core</artifactId><version>2.1.0.RELEASE</version>
</dependency>
2. 在Gateway module项目下创建config (package)包,添加SwaggerProvider文件
import lombok.AllArgsConstructor;
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 org.springframework.cloud.gateway.config.GatewayProperties;
import org.springframework.cloud.gateway.route.RouteLocator;import java.util.ArrayList;
import java.util.List;/*** @ClassName: SwaggerProvider* @Description: 聚合接口文档注册* @Author Gxin* @Date 2020/3/9 17:03* @Version: 1.0
**/
@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;@Overridepublic 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(),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;}
}
3. 创建handler包,添加SwaggerHandler文件
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.*;import java.util.Optional;@RestController
@RequestMapping("/swagger-resources")
public class SwaggerHandler {@Autowired(required = false)private SecurityConfiguration securityConfiguration;@Autowired(required = false)private UiConfiguration uiConfiguration;private final SwaggerResourcesProvider swaggerResources;@Autowiredpublic 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)));}
}
4. 在resources下添加application.yml
server:port: 8861
spring:application:name: @artifactId@cloud:gateway:discovery:locator:
# Gateway开启服务注册和发现功能enabled: true
# 将请求路径上的服务名配置为小写lowerCaseServiceId: trueroutes:- id: ozx-shop-service-weixin #网关路由uri: lb://OZX-SHOP-SERVICE-WEIXINpredicates:- Path=/wx/**
# StripPrefix的filter在转发之前将/wx去掉filters:- StripPrefix=1
# - SwaggerHeaderFilter- id: ozx-shop-service-memberuri: lb://OZX-SHOP-SERVICE-MEMBERpredicates:- Path=/mem/**# StripPrefix的filter在转发之前将/mem去掉filters:- StripPrefix=1eureka:instance:prefer-ip-address: trueclient:service-url:defaultZone: http://127.0.0.1:8761/eureka/
5.在业务module添加swagger2 maven 依赖
<dependency><!--添加Swagger依赖 --><groupId>io.springfox</groupId><artifactId>springfox-swagger2</artifactId><version>2.9.2</version>
</dependency>
<dependency><!--添加Swagger-UI依赖 --><groupId>io.springfox</groupId><artifactId>springfox-swagger-ui</artifactId><version>2.9.2</version>
</dependency>
<!--添加以下配置,java.lang.NumberFormatException: For input string: ""
解决Swagger2.9.2的NumberFormatException问题-->
<dependency><groupId>io.swagger</groupId><artifactId>swagger-annotations</artifactId><version>1.5.22</version>
</dependency>
<dependency><groupId>io.swagger</groupId><artifactId>swagger-models</artifactId><version>1.5.22</version>
</dependency>
6. 在业务module 添加SwaggerConfig文件
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import springfox.documentation.builders.ApiInfoBuilder;
import springfox.documentation.builders.PathSelectors;
import springfox.documentation.builders.RequestHandlerSelectors;
import springfox.documentation.service.ApiInfo;
import springfox.documentation.service.Contact;
import springfox.documentation.spi.DocumentationType;
import springfox.documentation.spring.web.plugins.Docket;
import springfox.documentation.swagger2.annotations.EnableSwagger2;/*** @ClassName: SwaggerConfig* @Description: 以yml文件配置方式配置swagger,类配置swagger属性已弃用* @Author Gxin* @Date 2020/1/9 16:32* @Version: 1.0**/
@Configuration
@EnableSwagger2
public class SwaggerConfig {@Beanpublic Docket createRestApi(){return new Docket(DocumentationType.SWAGGER_2).apiInfo(apiInfo()).select().apis(RequestHandlerSelectors.basePackage("swagger相关注解所在的包路径")).paths(PathSelectors.any()).build();}private ApiInfo apiInfo() {return new ApiInfoBuilder().title("Swagger API").description("接口文档").termsOfServiceUrl("团队网站").contact(new Contact("作者名","","电子邮箱")).version("版本号").build();}
}
7. 以application.yml文件配置swagger网页参数
swagger:base-package: com.ozx.ozxshopservicemember.controller #swagger相关注解所在的包路径title: SpringBoot2.x构建集成swagger2项目description: API文档自动生成version: 1.1terms-of-service-url: https://github.com/OGxincontact:name: Gxinemail: 电子邮箱url: https://github.com/OGxin
8. 添加Controller
package com.ozx.ozxshopservicemember.controller;
import com.alibaba.fastjson.JSONObject;
import com.ozx.ozxshopapimemberdto.input.UserInpDTO;
import com.ozx.ozxshopcommon.basic.BasicResponse;
import com.ozx.ozxshopserviceapimember.service.UserRegisterService;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;/*** @ClassName: UserResigterController* @Description: 用户注册模块* @Author Gxin* @Date 2020/3/9 15:15* @Version: 1.0**/
@RestController
@RequestMapping("/mem")
@ApiModel("用户注册模块")
public class UserResigterController {@Autowiredprivate UserRegisterService userRegisterService;@PostMapping("/reg")@ApiOperation(value = "注册",notes = "注册接口")@ApiImplicitParams({@ApiImplicitParam(name = "regCode",paramType = "query",value = "验证码",dataType = "String",example = "12345")})public BasicResponse<JSONObject> register(UserInpDTO userInpDTO,String regCode){return userRegisterService.register(userInpDTO, regCode);}
}