• Zuul整合Swagger,使用ZuulFilter解决下游服务context-path


    问题起因:使用Zuul网关服务,需要整合下游系统的swagger,但是下游服务存在context-path配置,无法正确跳转,最后使用ZuulFilter解决。

    1.Zuul整合下游swagger

    首先介绍一下Zuul如何整合下游服务swagger,很好理解,就是通过Zuul的swagger地址,实现将下游服务的swagger都放入同一个页面内,流转图如下:

    1.1 下游服务整合swagger

    这里进行简单介绍服务整合swagger的步骤其实就是分为两步:

    1. 配置swagger
    2. 对api和model等进行注释

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

    这里只新建了一个服务,服务名为test-service。

    1.2 Zuul聚合下游Swagger

    Zuul相关配置这里不做介绍,首先配置下游服务路由,即访问test-service/**转发到test-service服务,配置如下:

    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构建RESTful APIs")
                    .description("关注博主博客:https://www.dalaoyang.cn/")
                    .termsOfServiceUrl("https://www.dalaoyang.cn/")
                    .contact("dalaoyang")
                    .version("1.0")
                    .build();
        }
    }
    

    新建文档配置,这里主要目的是为了聚合下游服务的swagger,内容很好理解,就是讲SwaggerResource赋值,其中name为swagger的api文档名,location为对应api-docs地址,version为版本,这里利用ZuulProperties来生成对应文档,避免写死代码,完整内容如下:

    @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;
        }
    }
    

    配置到这里,其实已经完成了,访问网关swagger如图所示:

    2.下游服务存在context-path怎么办?

    从上面其实可以了解到,聚合文档的操作,其实就是将下游服务的/v2/api-docs整合进来,当然,可以在本文DocumentConfig中将下游服务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()) {
                //假设下游服务的context-path为服务名
                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;
        }
    }
    

    下游服务加入context-path配置,如下:

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

    启动服务,访问Zuul的swagger文档,还是可以同样的访问,但是测试一下在swagger请求一下下游服务api,如下

    很明显,404的原因就是因为转发下游服务的时候,没有加上context-path,在本文DocumentConfig配置的方式肯定不是正确的方式,那么如何解决呢?

    可以加入一个ZuulFilter来进行统一添加下游服务context-path,首先还原上面修改的DocumentConfig,接下来新建一个Filter继承ZuulFilter,创建一个转发前的拦截器,将转发地址进行修改,也就是我们需要的加入context-pa路径,由于本文下游context-path路径为服务名,所以案例比较简单,内容如下:

    @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;
        }
    }
    

    需要注意一点,这个拦截器需要在默认ZuulFilter后执行,才能获取requestURI和server。

    再次启动项目,就可以正常使用和访问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

  • 相关阅读:
    vue动态绑定class的几种方式
    寒假阅读笔记之《人月神话》
    人月神话阅读笔记1
    寒假阅读笔记之《构建之法》2
    寒假阅读笔记之《构建之法》
    家庭记账本APP(7)
    家庭记账本APP(6)
    家庭记账本APP(5)
    家庭记账本APP(4)
    家庭记账本APP(3)
  • 原文地址:https://www.cnblogs.com/dalaoyang/p/12005283.html
Copyright © 2020-2023  润新知