Zuul中聚合Swagger的坑

每一个服务都有本身的接口,经过Swagger来管理接口文档。在服务较多的时候咱们但愿有一个统一的入口来进行文档的查看,这个时候能够在zuul中进行文档的聚合显示。spring

下面来看下具体的整合步骤以及采坑记录。Cloud版本:Finchley.SR2, Boot版本:2.0.6api

加入Swagger的依赖:微信

<!-- Swagger -->
<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>

增长聚合代码:app

@EnableSwagger2
@Component
@Primary
public class DocumentationConfig implements SwaggerResourcesProvider {

    @Autowired
    private DiscoveryClient discoveryClient;
    
    @Value("${spring.application.name}")
    private String applicationName;
    
    @Override
    public List<SwaggerResource> get() {
        List<SwaggerResource> resources = new ArrayList<>();
        // 排除自身,将其余的服务添加进去
        discoveryClient.getServices().stream().filter(s -> !s.equals(applicationName)).forEach(name -> {
            resources.add(swaggerResource(name, "/" + name + "/v2/api-docs", "2.0"));
        });
        return resources;
    }

    private SwaggerResource swaggerResource(String name, String location, String version) {
        SwaggerResource swaggerResource = new SwaggerResource();
        swaggerResource.setName(name);
        swaggerResource.setLocation(location);
        swaggerResource.setSwaggerVersion(version);
        return swaggerResource;
    }

}

我这边直接用DiscoveryClient 获取服务列表进行聚合,固然你也能够固定写上你的服务列表,或者对接配置中心均可以。ide

其实除了DiscoveryClient 获取服务列表,咱们也能够根据zuul中路由的配置来获取,可使用RouteLocator 来操做。方式不少,用哪一种均可以。学习

正常状况下上面的整合步骤没任何问题,今天有朋友在星球提问,说本身的业务服务加了context-path,Zull中聚合的Swagger文档没法显示,由于路径错了,少了配置的context-path。效果以下图:ui

Swagger路径错误

也就是说在进行资源添加的时候须要将context-path加进去,也就是须要改动下面的代码:spa

resources.add(swaggerResource(name, "/" + name + "/v2/api-docs", "2.0"));

最简单的就是加一个配置,配置好每一个服务对应的context-path,这样在这里直接拼接上去就完事了。但这样显得有点低端呀,哈哈。code

DiscoveryClient 是很强大的,咱们能够用DiscoveryClient 来获取Eureka中的信息,此时我有了一个想法,那就是业务服务将自身的context-path放入Eureka的metadata-map中,而后Zuul中聚合的时候从metadata-map中获取context-path就好了。server

业务服务加配置:

server.servlet.context-path=/yinjihuan
eureka.instance.metadata-map.context-path=${server.servlet.context-path}

Zull中改造:

@Override
public List<SwaggerResource> get() {
    List<SwaggerResource> resources = new ArrayList<>();
    // 排除自身,将其余的服务添加进去
    discoveryClient.getServices().stream().filter(s -> !s.equals(applicationName)).forEach(name -> {
        Optional<ServiceInstance> instanceOptional = discoveryClient.getInstances(name).stream().findFirst();
        if (instanceOptional.isPresent() && instanceOptional.get().getMetadata().containsKey("context-path")) {
            String contexPath = instanceOptional.get().getMetadata().get("context-path");
            resources.add(swaggerResource(name, "/" + name + contexPath + "/v2/api-docs", "2.0"));
        } else {
            resources.add(swaggerResource(name, "/" + name + "/v2/api-docs", "2.0"));
        }
            
    });
    return resources;
}

这样就完美解决了增长context-path致使的问题,加入星球咱们一块儿学习吧。

欢迎加入个人知识星球,一块儿交流技术,免费学习猿天地的课程(http://cxytiandi.com/course

PS:目前星球中正在星主的带领下组队学习Spring Cloud,等你哦!

微信扫码加入猿天地知识星球

猿天地

相关文章
相关标签/搜索