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,等你哦!

微信掃碼加入猿天地知識星球

猿天地

相關文章
相關標籤/搜索