Springfox3 使用说明并整合 gateway 实现文档集中化

未解决的坑:

1.Basic用不了,Bearer的引用方式跟以前有点不一样
2.gateway网关统一管理 集中文档只能用SWAGGER_2(2.0),不能用OAS_30(3.0.3)
3.引入基础包的bean不能使用 BeanFactoryAware(导致不能创建多个group)
替换

Springfox3配置

引入包

现在只需要一个包 springboot的,不像以前需要两个,当然可以单独引用两个也行3.0的,具体可以进入这个包里看

            
                io.springfox
                springfox-boot-starter
                3.0.0
            

注解和访问地址 变更

由之前的 @EnableSwagger2 更改为 @EnableOpenApi,当然@EnableOpenAp可以放在配置类,也可以放在启动类上,项目访问地址从2.x的 http://localhost:8088/swagger-ui.html 到 3.x的 http://localhost:8088/swagger-ui/index.htmlhttp://localhost:8088/swagger-ui/

注:@EnableSwagger2在springfox3版本依然可以继续使用

DocumentationType 变更

Docket构造函数中的DocumentationType指向更改:由之前的DocumentationType.SWAGGER_2 更改为 DocumentationType.OAS_30

注:DocumentationType.SWAGGER_2在springfox3版本依然可以继续使用

@Bean
    public Docket createDocApi() {
        return new Docket(DocumentationType.OAS_30)
                .enable(swaggerProperties.getEnabled())
                .apiInfo(buildApiInfo(swaggerProperties.getDocketConfig()))
                .select()
                .apis(RequestHandlerSelectors.basePackage(swaggerProperties.getDocketConfig().getBasePackage()))
                .paths(buildPredicateSelector(swaggerProperties.getDocketConfig()))
                .build()
                .securitySchemes(Collections.singletonList(chooseAuthTypeScheme()))
                .securityContexts(Collections.singletonList(chooseAuthTypeContext()))
                ;
    }

断言Predicate变更

以前springfox2.x会默认引入guava 包,就像这个

 
      com.google.guava
      guava
      20.0
      compile
    

自从springfox官网github被其他老外提了issue吐槽guava落后,springfox3开始用了jdk8的Predicate,自此,springfox3只支持jdk8以上版本,这点要注意。
以下是我更新后predicate的配置:

private Predicate buildPredicateSelector(SwaggerProperties.DocketConfig config){
        // base-path处理
        List> basePath = new ArrayList<>();
        for (String path : config.getBasePath()) {
            basePath.add(PathSelectors.ant(path));
        }

        // exclude-path处理
        List> excludePath = new ArrayList<>();
        for (String path : config.getExcludePath()) {
            excludePath.add(PathSelectors.ant(path));
        }

        // 当没有配置任何path的时候,解析/.*
        if (config.getBasePath().isEmpty() || config.getBasePath() == null) {
            //return PathSelectors.regex("/.*");
            return PathSelectors.any().and(excludePath.stream().reduce(each -> true, (a,b) -> a.and(b.negate())));
        }

        //组装 base-path 和 exclude-path
        return basePath.stream().reduce(each -> false, Predicate::or)  //each为false原因是,如果是true,有任何or,都不会走右边
                .and(excludePath.stream().reduce(each -> true, (a,b) -> a.and(b.negate())));
    }

以上是springfox3的变更。

gateway网关实现集中化

说明

首先gateway默认是webflux,springfox2.x是没有整合webflux的(2.10除外),18年到现在两年没更新可能导致很多人都弃坑springfox,转openApi3了(另一个非官网组织)。而现在springfox3出现了,终于不用换包了。(主要是懒)
然后gateway这个服务同样引入上述包即可,只需引入,不用像2.10分两个注解 @EnableSwagger2WebMvc@EnableSwagger2WebFlux,只需引入@EnableOpenApi注解即可。

Nacos 实现方式

/**
 * 以nacos方式聚合各个服务的swagger接口文档, 直接获取nacos存活的服务
 *
 * @author lbj
 * @date 2020/09/22 18:25
 */
@Primary
@Component
@ConditionalOnProperty(prefix = "myyshop.swagger.provider", name = "type", havingValue = "nacos", matchIfMissing = true)
public class NacosSwaggerResourceProvider implements SwaggerResourcesProvider {
    /**
     * swagger2默认的url后缀
     */
    private static final String SWAGGER2URL = "/v2/api-docs";

    private static final String OAS_30_URL = "/v3/api-docs";

    @Autowired
    private NacosDiscoveryProperties nacosDiscoveryProperties;

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

    @Override
    public List get() {
        List resources = new ArrayList<>();

        String hasIpCount = "true";
        String withInstances = "false";
        String pageNo = "1";
        String pageSize = "1000";
        String httpUrlEx = "http://%s/nacos/v1/ns/catalog/services?hasIpCount=%s&withInstances=%s&pageNo=%s&pageSize=%s&serviceNameParam=&groupNameParam=%s&namespaceId=%s";
        String httpUrl = String.format(httpUrlEx, nacosDiscoveryProperties.getServerAddr(), hasIpCount, withInstances, pageNo, pageSize, nacosDiscoveryProperties.getGroup(), nacosDiscoveryProperties.getNamespace());
        ResponseEntity responseEntityMap = new RestTemplate().getForEntity(httpUrl, Map.class);
        Map responseMap = responseEntityMap.getBody();
        List serviceList = (List) responseMap.get("serviceList");
        Integer count = (Integer) responseMap.get("count");
        serviceList.stream().map(service -> String.valueOf(service.get("name"))).distinct()
                .forEach(serviceName -> {
                    String url = "/" + serviceName.toLowerCase() + SWAGGER2URL;
                    SwaggerResource swaggerResource = new SwaggerResource();
                    swaggerResource.setSwaggerVersion("2.0");
                    if(Objects.equals(serviceName.toLowerCase(), self)){
                        url = OAS_30_URL;
                        swaggerResource.setSwaggerVersion("3.0.3");
                    }
                    swaggerResource.setUrl(url);
                    swaggerResource.setName(serviceName);
                    resources.add(swaggerResource);
                });
        return resources;
    }
}

Gateway RouteLocator 实现方式

/**
 * 以gateway方式聚合各个服务的swagger接口文档(还可以加入healthy,去逐个匹配healthy,判断是否存活,活的话加入SwaggerResource列表,否则不加入)
 *
 * @author lbj
 * @date 2020/09/22 18:25
 */
@Primary
@Component
@ConditionalOnProperty(prefix = "myyshop.swagger.provider", name = "type", havingValue = "gateway")
public class GatewaySwaggerResourceProvider implements SwaggerResourcesProvider {
    /**
     * swagger2默认的url后缀
     */
    private static final String SWAGGER2URL = "/v2/api-docs";

    private static final String OAS_30_URL = "/v3/api-docs";
 
    /**
     * 网关路由
     */
    @Autowired
    private RouteLocator routeLocator;

    @Autowired
    private GatewayProperties gatewayProperties;
 
    /**
     * 网关应用名称
     */
    @Value("${spring.application.name}")
    private String self;
 
    @Override
    public List get() {
        List ds = gatewayProperties.getRoutes();
        List resources = new ArrayList<>();
        List routeHosts = new ArrayList<>();
        // 获取所有可用的host:serviceId
        routeLocator.getRoutes()
                .filter(route -> route.getUri().getHost() != null)
                .filter(route -> Objects.equals(route.getUri().getScheme(), "lb"))
//                .filter(route -> !self.equals(route.getUri().getHost()))
                .subscribe(route -> routeHosts.add(route.getUri().getHost()));
 
        // 记录已经添加过的server,存在同一个应用注册了多个服务在nacos上
        Set dealed = new HashSet<>();
        routeHosts.forEach(instance -> {
            // 拼接url
            String url = "/" + instance.toLowerCase() + SWAGGER2URL;
            if (!dealed.contains(url)) {
                dealed.add(url);
                SwaggerResource swaggerResource = new SwaggerResource();
                swaggerResource.setUrl(url);
                swaggerResource.setName(instance);
                //swaggerResource.setSwaggerVersion("3.0.3");
                resources.add(swaggerResource);
            }
        });
        return resources;
    }
}

你可能感兴趣的:(Springfox3 使用说明并整合 gateway 实现文档集中化)