Zuul整合Swagger,使用ZuulFilter解決下游服務(wù)context-path

問(wèn)題起因:使用Zuul網(wǎng)關(guān)服務(wù),需要整合下游系統(tǒng)的swagger,但是下游服務(wù)存在context-path配置,無(wú)法正確跳轉(zhuǎn),最后使用ZuulFilter解決。

1.Zuul整合下游swagger

首先介紹一下Zuul如何整合下游服務(wù)swagger,很好理解,就是通過(guò)Zuul的swagger地址,實(shí)現(xiàn)將下游服務(wù)的swagger都放入同一個(gè)頁(yè)面內(nèi),流轉(zhuǎn)圖如下:

image

1.1 下游服務(wù)整合swagger

這里進(jìn)行簡(jiǎn)單介紹服務(wù)整合swagger的步驟其實(shí)就是分為兩步:

  1. 配置swagger
  2. 對(duì)api和model等進(jìn)行注釋

這里不做代碼介紹,具體可以查看我的另一篇文章:https://www.dalaoyang.cn/article/21,或者查看本文源碼。

這里只新建了一個(gè)服務(wù),服務(wù)名為test-service。

1.2 Zuul聚合下游Swagger

Zuul相關(guān)配置這里不做介紹,首先配置下游服務(wù)路由,即訪問(wèn)test-service/**轉(zhuǎn)發(fā)到test-service服務(wù),配置如下:

zuul.routes.test-service.path=/test-service/**
zuul.routes.test-service.service-id=test-service

配置swagger配置文件,如下:

@Configuration
@EnableSwagger2
public class SwaggerConfig {

    @Bean
    public Docket createRestApi() {
        return new Docket(DocumentationType.SWAGGER_2)
                .apiInfo(apiInfo());
    }

    private ApiInfo apiInfo() {
        return new ApiInfoBuilder()
                .title("使用Swagger2構(gòu)建RESTful APIs")
                .description("關(guān)注博主博客:https://www.dalaoyang.cn/")
                .termsOfServiceUrl("https://www.dalaoyang.cn/")
                .contact("dalaoyang")
                .version("1.0")
                .build();
    }
}

新建文檔配置,這里主要目的是為了聚合下游服務(wù)的swagger,內(nèi)容很好理解,就是講SwaggerResource賦值,其中name為swagger的api文檔名,location為對(duì)應(yīng)api-docs地址,version為版本,這里利用ZuulProperties來(lái)生成對(duì)應(yīng)文檔,避免寫死代碼,完整內(nèi)容如下:

@Primary
@Component
public class DocumentConfig implements SwaggerResourcesProvider {

    @Autowired
    private ZuulProperties zuulProperties;

    @Override
    public List<SwaggerResource> get() {
        List<SwaggerResource> swaggerResources = new ArrayList<>();
        Map<String, ZuulProperties.ZuulRoute> routes = zuulProperties.getRoutes();
        for (String serviceName : routes.keySet()) {
            SwaggerResource swaggerResource = initSwaggerResource(serviceName,
                    "/" + serviceName + "/v2/api-docs", "1.0.0");
            swaggerResources.add(swaggerResource);
        }
        return swaggerResources;
    }

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

配置到這里,其實(shí)已經(jīng)完成了,訪問(wèn)網(wǎng)關(guān)swagger如圖所示:

image

2.下游服務(wù)存在context-path怎么辦?

從上面其實(shí)可以了解到,聚合文檔的操作,其實(shí)就是將下游服務(wù)的/v2/api-docs整合進(jìn)來(lái),當(dāng)然,可以在本文DocumentConfig中將下游服務(wù)context-path加入其中,注意注釋階段,完整代碼如下:

@Primary
@Component
public class DocumentConfig implements SwaggerResourcesProvider {

    @Autowired
    private ZuulProperties zuulProperties;

    @Override
    public List<SwaggerResource> get() {
        List<SwaggerResource> swaggerResources = new ArrayList<>();
        Map<String, ZuulProperties.ZuulRoute> routes = zuulProperties.getRoutes();
        for (String serviceName : routes.keySet()) {
            //假設(shè)下游服務(wù)的context-path為服務(wù)名
            SwaggerResource swaggerResource = initSwaggerResource(serviceName,
                    "/" + serviceName +"/" + serviceName + "/v2/api-docs", "1.0.0");
            swaggerResources.add(swaggerResource);
        }
        return swaggerResources;
    }

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

下游服務(wù)加入context-path配置,如下:

server.servlet.context-path=/test-service

啟動(dòng)服務(wù),訪問(wèn)Zuul的swagger文檔,還是可以同樣的訪問(wèn),但是測(cè)試一下在swagger請(qǐng)求一下下游服務(wù)api,如下

image

很明顯,404的原因就是因?yàn)檗D(zhuǎn)發(fā)下游服務(wù)的時(shí)候,沒(méi)有加上context-path,在本文DocumentConfig配置的方式肯定不是正確的方式,那么如何解決呢?

可以加入一個(gè)ZuulFilter來(lái)進(jìn)行統(tǒng)一添加下游服務(wù)context-path,首先還原上面修改的DocumentConfig,接下來(lái)新建一個(gè)Filter繼承ZuulFilter,創(chuàng)建一個(gè)轉(zhuǎn)發(fā)前的攔截器,將轉(zhuǎn)發(fā)地址進(jìn)行修改,也就是我們需要的加入context-pa路徑,由于本文下游context-path路徑為服務(wù)名,所以案例比較簡(jiǎn)單,內(nèi)容如下:

@Component
public class UrlPathFilter extends ZuulFilter {

    @Override
    public String filterType() {
        return FilterConstants.PRE_TYPE;
    }

    @Override
    public int filterOrder() {
        return 6;
    }

    @Override
    public boolean shouldFilter() {
        return true;
    }

    @Override
    public Object run() throws ZuulException {
        RequestContext requestContext = RequestContext.getCurrentContext();
        Object requestURI = requestContext.get(FilterConstants.REQUEST_URI_KEY);
        Object server = requestContext.get(FilterConstants.PROXY_KEY);
        String finalURI = "/" + server + requestURI;
        requestContext.put(FilterConstants.REQUEST_URI_KEY, finalURI);
        return null;
    }
}

需要注意一點(diǎn),這個(gè)攔截器需要在默認(rèn)ZuulFilter后執(zhí)行,才能獲取requestURI和server。

再次啟動(dòng)項(xiàng)目,就可以正常使用和訪問(wèn)swagger了。

3.源碼地址

Zuul地址:https://gitee.com/dalaoyang/springcloud_learn/tree/master/springcloud_swagger_zuul

Test-service地址:https://gitee.com/dalaoyang/springcloud_learn/tree/master/springcloud_swagger_service

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 一個(gè)90后小同事偶然在地鐵上跟我提到簡(jiǎn)書這個(gè)寫作平臺(tái),之前我是不了解有這個(gè)平臺(tái)的。也算是這個(gè)小伙伴一個(gè)不經(jīng)意的分享...
    03a6535caafd閱讀 380評(píng)論 0 4
  • 今天下午我剛來(lái)的時(shí)候,我都開(kāi)始寫試卷了。數(shù)學(xué)老師來(lái)了。我們班里就安靜下來(lái)了,班主任和張老師一來(lái)。班里就全沒(méi)有聲音了...
    05bf05316374閱讀 384評(píng)論 0 0
  • 根據(jù)國(guó)家發(fā)改委消息,新一輪成品油調(diào)價(jià)窗口將于12月2日24時(shí)開(kāi)啟。本次油價(jià)調(diào)整具體情況如下:汽油每噸上漲55元,柴...
    敬行閱讀 487評(píng)論 2 11
  • 有一個(gè)決心,我是下了一次又一次。每次都堅(jiān)持不了12小時(shí),就快速繳械投降!剛開(kāi)始的時(shí)候,自我安慰的理由是:自己...
    丹生閱讀 483評(píng)論 0 0

友情鏈接更多精彩內(nèi)容