zoukankan      html  css  js  c++  java
  • 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

  • 相关阅读:
    <原创>engine中地块的自动编号函数
    <原创>获取窗口上RadioButton的Tag值
    <原创>SQLServer一个高效的存储过程
    ArcEngine中放大、缩小、移动等功能实现的方法
    sublime No packages available for installation
    特殊字符,英文,中文排序
    关于 js中replace 特殊符号 ‘.’ 的问题
    12.3日电话面试
    electron 打包后node_modules 体积过于庞大
    git 本地同步分支数,删除远程已经删除掉的多余分支
  • 原文地址:https://www.cnblogs.com/dalaoyang/p/12005283.html
Copyright © 2011-2022 走看看