问题起因:使用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

Zuul整合Swagger,使用ZuulFilter解决下游服务context-path的更多相关文章

  1. Spring Cloud Zuul 网关的分布式系统中整合Swagger(转)和 zuul跨域访问问题

    首先恭喜自己终于找对了努力的方向,很荣幸能在公司接触到微服务架构,也很高兴公司一个大佬哥们愿意带我,他技术确实很牛逼,我也很佩服他,前后端通吃,干了六年能有这样的水平.最近跟着在搞微服务架构,给我分配 ...

  2. 如何Spring Cloud Zuul作为网关的分布式系统中整合Swagger文档在同一个页面上

    本文不涉及技术,只是单纯的一个小技巧. 阅读本文前,你需要对spring-cloud-zuul.spring-cloud-eureka.以及swagger的配置和使用有所了解. 如果你的系统也是用zu ...

  3. springcloud+gateway微服务整合swagger

    单一的微服务集成swagger: maven: <dependency> <groupId>io.springfox</groupId> <artifactI ...

  4. springboot+cloud 学习(四)Zuul整合Swagger2

    前言 在微服务架构下,服务是分散的,怎么把所有服务接口整合到一起是我们需要关注的. 下面举例用zuul作为分布式系统的网关,同时使用swagger生成文档,想把整个系统的文档整合在同一个页面上来说明. ...

  5. springboot整合swagger。完爆前后端调试

    web接口开发时在调试阶段最麻烦的就是参数调试,前端需要咨询后端.后端有时候自己也不是很了解.这时候就会造成调试一次接口就需要看一次代码.Swagger帮我们解决对接的麻烦 springboot接入s ...

  6. springmvc整合swagger

    前言 Swagger 是一个规范和完整的框架,用于生成.描述.调用和可视化 RESTful 风格的 Web 服务.总体目标是使客户端和文件系统作为服务器以同样的速度来更新.文件的方法,参数和模型紧密集 ...

  7. Spring Boot初识(3)- Spring Boot整合Swagger

    一.本文介绍 如果Web项目是完全前后端分离的话(我认为现在完全前后端分离已经是趋势了)一般前端和后端交互都是通过接口的,对接口入参和出参描述的文档就是Mock文档.随着接口数量的增多和参数的个数增加 ...

  8. Spring MVC 整合Swagger的一些问题总结

    在做Spring MVC 整合swagger的时候,遇到的两个问题: 第一个问题 在网上找了一些Spring MVC 和Swagger的例子,照着一步步的配置,结果,到最后,项目都起来了,没有任何问题 ...

  9. Spring Boot:整合Swagger文档

    综合概述 spring-boot作为当前最为流行的Java web开发脚手架,越来越多的开发者选择用其来构建企业级的RESTFul API接口.这些接口不但会服务于传统的web端(b/s),也会服务于 ...

随机推荐

  1. redis的3种过期键删除策略

    Redis的过期键的过期时间都保存在过期字典中,过期键的删除策略有三种,分别是定时删除.惰性删除和定期删除. 定时删除 定时删除策略,是指在设置键的过期时间的同时,创建一个定时器,让定时器在键的过期时 ...

  2. 关于@Autowired后Spring无法注入的问题

    1.对于新手来说,最明显的不过是在applicationContext.xml文件上没有加<context:component-scan base-package="com.xxx&q ...

  3. KVM学习笔记--静态迁移

    .静态迁移过程如下 (1)确定虚拟机关闭状态 (2)准备迁移oeltest02虚拟机,查看该虚拟机配置的磁盘文件 (3)导入虚拟机配置文件 [root@node1~]# virsh dumpxml o ...

  4. 使用角色管理工具 安装或配置microsoft.net framework 3.5 sp1

    解决方法:

  5. Flask--闪现、中间件、多app应用

    目录 闪现 源码 案例 中间件 自定义局部中间件 自定义全局装饰器 多app应用 闪现 flask提供了一个非常有用的flash()函数,它可以用来"闪现"需要提示给用户的消息,比 ...

  6. Java异常相关知识总结

    异常: 概述:java程序运行过程中出现的错误 常见的异常: StackOverflowError ArrayIndexOutOfBoundsException NullPointerExceptio ...

  7. vue Router——进阶篇

    vue Router--基础篇 1.导航守卫 正如其名,vue-router 提供的导航守卫主要用来通过跳转或取消的方式守卫导航.有多种机会植入路由导航过程中:全局的, 单个路由独享的, 或者组件级的 ...

  8. 转 echarts 的使用时遇到的坑 初始化和销毁,亲测有效!

    纵观ECharts图表实例化的API,主要有一下几个相关的实例化方法: 1.setOption(Object option,{boolean = true} notMerge) 参数: 1).Obje ...

  9. map、filter、reduce函数的使用

    1.filter() 作用:过滤 // 1.筛选出大于30的数. const array = [10, 20, 30, 40, 50, 60, 70, 80] // 普通写法 // let newar ...

  10. web下载附件及修改名称

    /** * @param: url 附件地址 * @param: filename 下载后的文件名 */ function download(url, filename) { getBlob(url, ...