zoukankan      html  css  js  c++  java
  • Zuul中聚合Swagger的坑

    每个服务都有自己的接口,通过Swagger来管理接口文档。在服务较多的时候我们希望有一个统一的入口来进行文档的查看,这个时候可以在zuul中进行文档的聚合显示。

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

    加入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>
    

    增加聚合代码:

    @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 获取服务列表进行聚合,当然你也可以固定写上你的服务列表,或者对接配置中心都可以。

    其实除了DiscoveryClient 获取服务列表,我们也可以根据zuul中路由的配置来获取,可以使用RouteLocator 来操作。方式很多,用哪种都可以。

    正常情况下上面的整合步骤没任何问题,今天有朋友在星球提问,说自己的业务服务加了context-path,Zull中聚合的Swagger文档无法显示,因为路径错了,少了配置的context-path。效果如下图:

    Swagger路径错误

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

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

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

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

    业务服务加配置:

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

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

    猿天地

  • 相关阅读:
    MHA自动切换流程
    手写源码之 简单实现on emit off
    手写源码 -- bind,call,aplly
    多维数组转化为一维数组
    electron+vue中使用nodeJs的fs模块以及上传文件
    制作海报
    vue中引入播放器(百度播放器和腾讯云播放器)
    webpack配置
    webpack
    css样式
  • 原文地址:https://www.cnblogs.com/yinjihuan/p/10799283.html
Copyright © 2011-2022 走看看