SpringCloud整合Swagger

337 阅读3分钟

SpringBoot:2.1.6

SpringCloudAlibaba:2.1.2

SpringBoot项目使用Swagger的话需要独立配置,但是在SpringCloud中,只需要在gateway进行详细配置即可。

Gateway:一个依赖、三个配置文件以及断言配置。

1:微服务配置Swagger

<dependency>
    <groupId>com.github.xiaoymin</groupId>
    <artifactId>knife4j-spring-boot-starter</artifactId>
    <version>3.0.3</version>
</dependency>

如果报插件问题,请在微服务中引入这个

<!-- swagger使用插件 -->
<dependency>
    <groupId>org.springframework.plugin</groupId>
    <artifactId>spring-plugin-core</artifactId>
    <version>2.0.0.RELEASE</version>
</dependency>

2:Gateway配置统一获取

依赖:

<dependency>
    <groupId>com.github.xiaoymin</groupId>
    <artifactId>knife4j-spring-boot-starter</artifactId>
    <version>3.0.3</version>
</dependency>

配置文件:

import org.springframework.beans.factory.annotation.Value;
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.spi.DocumentationType;
import springfox.documentation.spring.web.plugins.Docket;
​
@Configuration
public class Knife4jConfiguration {
​
    @Value("${swagger.enable:true}")
    private boolean enableSwagger;
​
    @Bean(value = "defaultApi2")
    public Docket createRestApi() {
        return new Docket(DocumentationType.SWAGGER_2)
                .apiInfo(new ApiInfoBuilder()
                            .title("服务")
                            .version("1.0")
                            .build())
                .enable(enableSwagger)
                .select()
                .apis(RequestHandlerSelectors.basePackage("com.test"))
                .paths(PathSelectors.any())
                .build();
    }
​
}
import rg.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.RestController;
import reactor.core.publisher.Mono;
import springfox.documentation.swagger.web.*;
​
import java.util.Optional;
​
@RestController
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;
    }
​
    /**
     * Swagger安全配置,支持oauth和apiKey设置
     */
    @GetMapping("/swagger-resources/configuration/security")
    public Mono<ResponseEntity<SecurityConfiguration>> securityConfiguration() {
        return Mono.just(new ResponseEntity<>(
                Optional.ofNullable(securityConfiguration).orElse(SecurityConfigurationBuilder.builder().build()), HttpStatus.OK));
    }
​
    /**
     * Swagger UI配置     */
    @GetMapping("/swagger-resources/configuration/ui")
    public Mono<ResponseEntity<UiConfiguration>> uiConfiguration() {
        return Mono.just(new ResponseEntity<>(
                Optional.ofNullable(uiConfiguration).orElse(UiConfigurationBuilder.builder().build()), HttpStatus.OK));
    }
​
    /**
     * Swagger资源配置,微服务中这各个服务的api-docs信息
     */
    @GetMapping("/swagger-resources")
    public Mono<ResponseEntity> swaggerResources() {
        return Mono.just((new ResponseEntity<>(swaggerResources.get(), HttpStatus.OK)));
    }
}
package com.qd.gateway.config;
​
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;
​
@Component
@Primary
public class SwaggerResourceConfig implements SwaggerResourcesProvider {
​
    private final RouteLocator routeLocator;
    private final GatewayProperties gatewayProperties;
​
    public SwaggerResourceConfig(RouteLocator routeLocator, GatewayProperties gatewayProperties) {
        this.routeLocator = routeLocator;
        this.gatewayProperties = gatewayProperties;
    }
​
    @Override
    public List<SwaggerResource> get() {
        List<SwaggerResource> resources = new ArrayList<>();
        List<String> routes = new ArrayList<>();
        //获取所有路由的ID
        routeLocator.getRoutes().subscribe(route -> routes.add(route.getId()));
        //过滤出配置文件中定义的路由->过滤出Path Route Predicate->根据路径拼接成api-docs路径->生成SwaggerResource
        gatewayProperties.getRoutes().stream().filter(routeDefinition -> routes.contains(routeDefinition.getId())).forEach(route -> {
            route.getPredicates().stream()
                    .filter(predicateDefinition -> ("Path").equalsIgnoreCase(predicateDefinition.getName()))
                    .forEach(predicateDefinition -> resources.add(swaggerResource(route.getId(),
                            predicateDefinition.getArgs().get(NameUtils.GENERATED_NAME_PREFIX + "0")
                                    .replace("**", "v2/api-docs"))));
        });
​
        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实现统一获取接口文档是通过两个方法:
这个是获取微服务的定义文件
http://localhost:9000/swagger-resources
这个是获取接口的JSON文档
http://localhost:9000/test/v2/api-docs
​
Swagger配置文件:Knife4jConfiguration
Security配置文件:SwaggerHandler
生成服务列表:SwaggerResourceConfig
​
SwaggerResourceConfig:是通过获取gateway的配置,然后拼接地址(例如:127.0.0.1:9000/test/v2/api-docs),依次请求(/test/**的路径是交由cloud-user-service处理)
​
网上大多数的配置是以下这个,如果对某个服务请求路径截取,那你就需要在接口的请求路径上加上一个前缀,不然会导致无法访问
filters:
  - StripPrefix=1
​
而这个配置就不用给接口路径添加前缀,他专门对swagger的请求进行了截取,就不会有正常配置无法请求的问题
filters:
  - RewritePath=/test/v2/api-docs, /v2/api-docs
server:
  port: 9000
Spring:
  application:
    name: cloud-gateway-server
  cloud:
    gateway:
      routes: #配置路由
        - id: cloud-user-router
          uri: lb://cloud-user-service
          predicates:
            - Path=/test/**,/api/**
          filters:
            - RewritePath=/test/v2/api-docs, /v2/api-docs
            - RewritePath=/api/v2/api-docs, /v2/api-docs
    discovery:
      locator:
        enabled: true #开启从注册中心动态创建路由的功能
        lower-case-service-id: true #使用小写服务名,默认是大写
      globalcors: # 全局的跨域处理
        add-to-simple-url-handler-mapping: true # 解决options请求被拦截问题
        corsConfigurations:
          '[/**]':
            allowedOrigins: # 允许哪些网站的跨域请求 allowedOrigins: “*” 允许所有网站
              - "*"
            allowedMethods: # 允许的跨域ajax的请求方式
              - "GET"
              - "POST"
              - "DELETE"
              - "PUT"
              - "OPTIONS"
            allowedHeaders: "*" # 允许在请求中携带的头信息
            allowCredentials: true # 是否允许携带cookie
            maxAge: 360000 # 这次跨域检测的有效期