Spring Cloud Gateway聚合Swagger2文档(初始版)

在spring Cloud架构下,由于各个微服务拥有独立的Swagger接口文档,但我们不可能每次零散地通过各个服务的端口去访问需要查看的服务接口文档,所以为了能更加直观方便地查看,我们可以在Spring Cloud Gateway网关模块聚合各微服务的Swagger接口文档。

依赖版本:
依赖 版本
Spring Boot 2.3.0.RELEASE
Spring Cloud Hoxton.SR4
springfox-swagger2 2.8.0
springfox-swagger-ui 2.8.0

这里只贴关键代码:

admin-user用户服务:

swagger配置文件:


import com.fasterxml.classmate.GenericType;
import com.fasterxml.classmate.TypeResolver;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.HttpHeaders;
import org.springframework.web.context.request.async.DeferredResult;
import springfox.documentation.builders.ApiInfoBuilder;
import springfox.documentation.builders.PathSelectors;
import springfox.documentation.builders.RequestHandlerSelectors;
import springfox.documentation.schema.WildcardType;
import springfox.documentation.service.ApiInfo;
import springfox.documentation.service.ApiKey;
import springfox.documentation.service.AuthorizationScope;
import springfox.documentation.service.SecurityReference;
import springfox.documentation.spi.DocumentationType;
import springfox.documentation.spi.service.contexts.SecurityContext;
import springfox.documentation.spring.web.plugins.Docket;
import springfox.documentation.swagger2.annotations.EnableSwagger2;

import java.util.*;

import static springfox.documentation.schema.AlternateTypeRules.newRule;

/**
 * swagger接口文档配置
 * @Author: ZJH
 * @Date: 2019/12/5 10:15
 */

@Configuration
@EnableSwagger2
public class SwaggerConfig {
    // swagger接口界面访问路径 :http://localhost:9800/swagger-ui.html  IP为机器的IP,端口号为工程的端口

    @Autowired
    private TypeResolver typeResolver;

    @Bean
    public Docket api() {
        return new Docket(DocumentationType.SWAGGER_2)
                .apiInfo(apiInfo())
                .select()
                // api接口路径,即controller层路径
                .apis(RequestHandlerSelectors.basePackage("com.example.user"))
                // 指定路径处理PathSelectors.any()代表所有的路径(除了被@ApiIgnore指定的请求)
                .paths(PathSelectors.any())
                .build()
                .alternateTypeRules(
                        newRule(
                                typeResolver.resolve(
                                        DeferredResult.class,
                                        typeResolver.resolve(GenericType.class, WildcardType.class)
                                ),
                                typeResolver.resolve(WildcardType.class)
                        )
                )
                // 支持的协议
                .protocols(newHashSet("https", "http"))
                .securitySchemes(securitySchemes())
                .securityContexts(securityContexts());
    }

    private ApiInfo apiInfo() {
        return new ApiInfoBuilder()
                .title("后台用户管理api")
                .description("后台用户管理接口")
                .version("2.0")
                .build();
    }

    /**
     * 设置授权信息
     */
    private List<ApiKey> securitySchemes() {
        // 在请求头header添加一个名为Authorization的token
        return Collections.singletonList(new ApiKey(HttpHeaders.AUTHORIZATION, "token", "header"));
    }

    /**
     * 授权信息全局应用
     */
    private List<SecurityContext> securityContexts() {
        return Collections.singletonList(
                SecurityContext.builder()
                        .securityReferences(
                                Collections.singletonList(new SecurityReference("Authorization",
                                        new AuthorizationScope[]{new AuthorizationScope("global", "")}
                                )))
                        // 可通过配置正则表达式去排除一些不需要携带token访问的接口 这里不做特殊处理,全部接口访问都需要携带
                        // 比如.forPaths(PathSelectors.regex("^(?!auth).*$"))  对所有包含"auth"的接口不需要使用securitySchemes
                        .forPaths(PathSelectors.any())
                        .build()
        );
    }

    @SafeVarargs
    private final <T> Set<T> newHashSet(T... ts) {
        if (ts.length > 0) {
            return new LinkedHashSet<>(Arrays.asList(ts));
        }
        return null;
    }
}

gateway-web网关服务:

由于网关服务层不写业务逻辑代码,所以不需要配置Swagger展示接口(Spring Cloud Gateway依赖webflux,Swagger2未来版本会支持),仅需通过继承SwaggerResourcesProvider接口构造swagger资源来聚合各服务Swagger接口。

import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cloud.gateway.route.RouteLocator;
import org.springframework.context.annotation.Primary;
import org.springframework.stereotype.Component;
import springfox.documentation.swagger.web.SwaggerResource;
import springfox.documentation.swagger.web.SwaggerResourcesProvider;

import javax.annotation.Resource;
import java.net.URI;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 聚合各服务swagger接口,继承SwaggerResourcesProvider接口构造swagger资源
 * @Author: ZJH
 * @Date: 2020/2/24 13:29
 */

@Primary
@Component
@Slf4j
public class SwaggerProvider implements SwaggerResourcesProvider {

    /**
     * swagger默认的url后缀
     */
    protected static final String API_URI = "/v2/api-docs";

    /**
     * 网关路由 对应配置文件的spring.cloud.gateway.route的路由集合
     */
    @Resource
    private RouteLocator routeLocator;

    /**
     * 网关应用名称
     */
    @Value("${spring.application.name}")
    private String appName;


    @Override
    public List<SwaggerResource> get() {
        List<SwaggerResource> resources = new ArrayList<>();
        /*SwaggerResource gatewayResource = new SwaggerResource();
        gatewayResource.setUrl(API_URI);
        gatewayResource.setName("gateway");
        resources.add(gatewayResource);*/

        Map<String, URI> routesMap = new HashMap<>(8);
        // 获取网关中配置的路由
        routeLocator.getRoutes().filter(route -> route.getUri().getHost() != null)
                .filter(route -> !appName.equals(route.getUri().getHost()))
                .subscribe(route -> routesMap.put(route.getUri().getHost(), route.getUri()));

        routesMap.forEach((name, uri) -> {
            String url = "/" + uri.getHost() + API_URI;
            SwaggerResource swaggerResource = new SwaggerResource();
            swaggerResource.setUrl(url);
            swaggerResource.setUrl(url);
            swaggerResource.setName(name);
            swaggerResource.setSwaggerVersion("2.0");
            resources.add(swaggerResource);
        });
        log.info("routesMap===============:" + routesMap.toString());
        return resources;
    }
}

最后分别启动这两个服务,访问Swagger展示界面(http://localhost:9800/swagger-ui.html IP为机器的IP,端口号为网关服务的端口),可看到:
Spring Cloud Gateway聚合Swagger2文档(初始版)_第1张图片

你可能感兴趣的:(java)