gateway整合swagger2
一、maven依赖
1、网关依赖(此处注册中心采用nacos)
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
<version>2.2.1.RELEASE</version>
<exclusions>
<exclusion>
<groupId>com.alibaba.nacos</groupId>
<artifactId>nacos-client</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>com.alibaba.nacos</groupId>
<artifactId>nacos-client</artifactId>
<version>1.3.2</version>
</dependency>
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
<version>2.2.1.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-gateway</artifactId>
<version>2.2.1.RELEASE</version>
</dependency>
2、swagger2依赖
<dependency> <groupId>io.springfox</groupId> <artifactId>springfox-swagger2</artifactId> <version>2.9.2</version> <exclusions> <exclusion> <groupId>org.springframework</groupId> <artifactId>*</artifactId> </exclusion> </exclusions> </dependency> <dependency> <groupId>com.github.xiaoymin</groupId> <artifactId>swagger-bootstrap-ui</artifactId> <version>1.9.6</version> </dependency>
二、网关配置文件
bootstrap.yml文件
spring:
application:
name: gateway
profiles:
active: local
# 开启 Gateway 服务注册中心服务发现
cloud:
gateway:
discovery:
locator:
enabled: on
#使用服务名称的小写(服务名称不能带下划线)
lower-case-service-id: on
nacos:
config:
#配置文件后缀名
file-extension: yaml
refresh-enabled: true
#允许覆盖已经存在的同名bean
main:
allow-bean-definition-overriding: true
bootstrap-local.yml文件
server:
port: 8081
spring:
cloud:
nacos:
discovery:
server-addr: 127.0.0.1:8848
config:
server-addr: 127.0.0.1:8848
group: local
log:
level: INFO
#日志保存时间(天)
maxHistory: 2
#每个日志文件的大小
maxSize: 10MB
logback-spring.xml文件(logback文件)
1 <?xml version="1.0" encoding="UTF-8"?> 2 <configuration> 3 <springProperty scope="context" name="loglevel" source="log.level"/> 4 <springProperty scope="context" name="maxHistory" source="log.maxHistory"/> 5 <springProperty scope="context" name="maxSize" source="log.maxSize"/> 6 <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender"> 7 <encoder> 8 <pattern>%d{yyyy-MM-dd HH:mm:ss}[%level][%thread][%logger]-%msg%n</pattern> 9 <charset>UTF-8</charset> 10 </encoder> 11 </appender> 12 <!-- Perf4J logger Appender --> 13 <appender name="DailyAndSizeRollAppender" class="ch.qos.logback.core.rolling.RollingFileAppender"> 14 <file>logs/gateway.log</file> 15 <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy"> 16 <!-- rollover daily --> 17 <fileNamePattern>logs/lt_gateway.%i.%d{yyyy-MM-dd}.log.zip</fileNamePattern> 18 <timeBasedFileNamingAndTriggeringPolicy 19 class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP"> 20 <!-- or whenever the file size reaches 200MB --> 21 <maxFileSize>${maxSize}</maxFileSize> 22 </timeBasedFileNamingAndTriggeringPolicy> 23 <maxHistory>${maxHistory}</maxHistory> 24 </rollingPolicy> 25 <encoder> 26 <pattern>%d{yyyy-MM-dd HH:mm:ss}[%level][%thread][%logger]-%msg%n</pattern> 27 <charset>UTF-8</charset> 28 </encoder> 29 </appender> 30 <appender name="logApiAccess" class="ch.qos.logback.core.rolling.RollingFileAppender"> 31 <file>logs/api_access/access.log</file> 32 <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy"> 33 <!-- rollover daily --> 34 <fileNamePattern>logs/api_access/access.log.%i.%d{yyyy-MM-dd}.log.zip 35 </fileNamePattern> 36 <timeBasedFileNamingAndTriggeringPolicy 37 class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP"> 38 <!-- or whenever the file size reaches 200MB --> 39 <maxFileSize>200MB</maxFileSize> 40 </timeBasedFileNamingAndTriggeringPolicy> 41 <maxHistory>7</maxHistory> 42 </rollingPolicy> 43 <encoder> 44 <pattern>%msg%n</pattern> 45 </encoder> 46 </appender> 47 <!--监控指定的日志类 并输出到指定的文件中--> 48 <logger name="com.xx.xx.LogApiAccessUtil" level="${loglevel}"> 49 <appender-ref ref="logApiAccess"/> 50 </logger> 51 <root level="${loglevel}"> 52 <appender-ref ref="STDOUT"/> 53 <appender-ref ref="DailyAndSizeRollAppender"/> 54 </root> 55 </configuration>
三、swagger2配置类
1、获取不同微服务的提供者
1 public static final String SWAGGER2URL = "/v2/api-docs";
2 private final RouteLocator routeLocator;
3
4 @Value("${spring.application.name}")
5 private String self;
6
7 public SwaggerConfig(RouteLocator routeLocator) {
8 this.routeLocator = routeLocator;
9 }
10
11 @Override
12 public List<SwaggerResource> get() {
13 List<SwaggerResource> resources = new ArrayList<>();
14 List<String> routeHosts = new ArrayList<>();
15 // 由于我的网关采用的是负载均衡的方式,因此我需要拿到所有应用的serviceId
16 // 获取所有可用的host:serviceId
17 routeLocator.getRoutes().filter(route -> route.getUri().getHost() != null)
18 .filter(route -> !self.equals(route.getUri().getHost()))
19 .subscribe(route -> routeHosts.add(route.getUri().getHost()));
20
21 // 记录已经添加过的server,存在同一个应用注册了多个服务在nacos上
22 Set<String> dealed = new HashSet<>();
23 routeHosts.forEach(instance -> {
24 // 拼接url,样式为/serviceId/v2/api-info,当网关调用这个接口时,会自动通过负载均衡寻找对应的主机
25 String url = "/" + instance + SWAGGER2URL;
26 if (!dealed.contains(url)) {
27 dealed.add(url);
28 SwaggerResource swaggerResource = new SwaggerResource();
29 swaggerResource.setUrl(url);
30 swaggerResource.setName(instance);
31 resources.add(swaggerResource);
32 }
33 });
34 return resources;
35 }
2、聚合接口类
1 @RestController 2 public class SwaggerHandler { 3 4 @Autowired(required = false) 5 private SecurityConfiguration securityConfiguration; 6 7 @Autowired(required = false) 8 private UiConfiguration uiConfiguration; 9 10 private final SwaggerResourcesProvider swaggerResources; 11 12 @Autowired 13 public SwaggerHandler(SwaggerResourcesProvider swaggerResources) { 14 this.swaggerResources = swaggerResources; 15 } 16 17 @GetMapping("/swagger-resources/configuration/security") 18 public Mono<ResponseEntity<SecurityConfiguration>> securityConfiguration() { 19 return Mono.just(new ResponseEntity<>( 20 Optional.ofNullable(securityConfiguration).orElse(SecurityConfigurationBuilder.builder().build()), HttpStatus.OK)); 21 } 22 23 @GetMapping("/swagger-resources/configuration/ui") 24 public Mono<ResponseEntity<UiConfiguration>> uiConfiguration() { 25 return Mono.just(new ResponseEntity<>( 26 Optional.ofNullable(uiConfiguration).orElse(UiConfigurationBuilder.builder().build()), HttpStatus.OK)); 27 } 28 29 @GetMapping("/swagger-resources") 30 public Mono<ResponseEntity> swaggerResources() { 31 return Mono.just((new ResponseEntity<>(swaggerResources.get(), HttpStatus.OK))); 32 } 33 34 @GetMapping("/") 35 public Mono<ResponseEntity> swaggerResourcesN() { 36 return Mono.just((new ResponseEntity<>(swaggerResources.get(), HttpStatus.OK))); 37 } 38 39 @GetMapping("/csrf") 40 public Mono<ResponseEntity> swaggerResourcesCsrf() { 41 return Mono.just((new ResponseEntity<>(swaggerResources.get(), HttpStatus.OK))); 42 }
3、解决访问/v2/api/docs 404的问题
@Component
public class SwaggerHeaderFilter extends AbstractGatewayFilterFactory {
@Override
public GatewayFilter apply(Object config) {
return (exchange, chain) -> {
ServerHttpRequest request = exchange.getRequest();
String path = request.getURI().getPath();
if (!StringUtils.endsWithIgnoreCase(path, SwaggerConfig.SWAGGER2URL)) {
return chain.filter(exchange);
}
ServerHttpRequest newRequest = request.mutate().build();
ServerWebExchange newExchange = exchange.mutate().request(newRequest).build();
return chain.filter(newExchange);
};
}
}
四、微服务的相关配置
1、maven依赖
<dependency> <groupId>com.alibaba.cloud</groupId> <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId> <version>2.2.1.RELEASE</version> <exclusions> <exclusion> <groupId>com.alibaba.nacos</groupId> <artifactId>nacos-client</artifactId> </exclusion> </exclusions> </dependency> <dependency> <groupId>com.alibaba.nacos</groupId> <artifactId>nacos-client</artifactId> <version>1.3.2</version> </dependency> <dependency> <groupId>com.alibaba.cloud</groupId> <artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId> <version>2.2.1.RELEASE</version> </dependency> <dependency> <groupId>io.springfox</groupId> <artifactId>springfox-swagger2</artifactId> <version>2.9.2</version> </dependency> <dependency> <groupId>io.springfox</groupId> <artifactId>springfox-swagger-ui</artifactId> <version>2.9.2</version> </dependency> <dependency> <groupId>io.swagger</groupId> <artifactId>swagger-annotations</artifactId> <version>1.5.21</version> </dependency> <dependency> <groupId>io.swagger</groupId> <artifactId>swagger-models</artifactId> <version>1.5.21</version> </dependency> <dependency> <groupId>com.github.xiaoymin</groupId> <artifactId>swagger-bootstrap-ui</artifactId> <version>1.9.6</version> </dependency>
2、配置文件
bootstrap.yml文件
spring: application: name: dcjcgl profiles: active: local jackson: time-zone: GMT+8 date-format: yyyy-MM-dd HH:mm:ss servlet: multipart: #单文件大小 max-file-size: 512MB #总上传文件大小 max-request-size: 512MB enabled: true file-size-threshold: 0 cloud: nacos: config: #配置文件后缀名 file-extension: yaml refresh-enabled: true #允许覆盖已经存在的同名bean main: allow-bean-definition-overriding: true
bootstrap-local.yml文件
server: port: 8083 spring: cloud: nacos: discovery: server-addr: 127.0.0.1:8848 config: server-addr: 127.0.0.1:8848 group: local #日志配置 log: level: INFO #日志保存时间(天) maxHistory: 2 #每个日志文件的大小 maxSize: 10MB
3、配置类
@Configuration
@EnableSwagger2
public class SwaggerConfig {
@Bean
public Docket docket(){
return new Docket(DocumentationType.SWAGGER_2)
.apiInfo(apiInfo())
.select()
.apis(RequestHandlerSelectors.basePackage("com.xx.xx.web"))
.paths(PathSelectors.any())
.build();
}
public ApiInfo apiInfo(){
return new ApiInfoBuilder()
.title("xx模块相关接口")
.description("用restful风格写接口")
.termsOfServiceUrl("")
.version("1.0")
.build();
}
4、访问地址
http://127.0.0.1:8080/doc.html