前言

通过之前的两篇文章,可以简单的搭建一个路由网关了。而我们知道,现在都奉行前后端分离开发,前后端开发的沟通成本就增加了,所以一般上我们都是通过swagger进行api文档生成的。现在由于使用了统一路由网关了,都希望各微服务的api文档统一的聚合在网关服务中,也方便前端用户查阅,不需要每个服务单独查看。当然了,也是可以做一个文档索引网页进行各微服务的api文档链接的。今天,我们就来讲下使用swagger实现自动化聚合微服务文档功能。

注:关于Swagger的介绍和使用,由于在之前的SpringBoot系列文章中有提及,这里就不在过多阐述了,不理解的可以点击:第十章:Swagger2的集成和使用进行查看,了解下基本用法。

Zuul聚合示例

为了实现自动聚合功能,简单来说就是通过Zuulapi获取所有的路由信息,根据其具体地址进行自动转配到SwaggerSwaggerResource下。

另外,为了项目的独立,本章节创建个maven多模块工程项目。整体结构如下:

同时,会启动一个基于Eureka的注册服务,具体可以查看源码:spring-cloud-eureka-server

微服务端

为了演示,创建两个微服务spring-cloud-zuul-service-onespring-cloud-zuul-service-two

这里以构建spring-cloud-zuul-service-one为例,spring-cloud-zuul-service-two基本上是一样的,可以查看源码示例。

0.引入相关依赖

  1. <dependency>
  2. <groupId>org.springframework.boot</groupId>
  3. <artifactId>spring-boot-starter-web</artifactId>
  4. </dependency>
  5. <!-- 客户端依赖 -->
  6. <dependency>
  7. <groupId>org.springframework.cloud</groupId>
  8. <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
  9. </dependency>
  10. <!--swagger -->
  11. <dependency>
  12. <groupId>io.springfox</groupId>
  13. <artifactId>springfox-swagger2</artifactId>
  14. <version>2.9.0</version>
  15. </dependency>
  16. <dependency>
  17. <groupId>io.springfox</groupId>
  18. <artifactId>springfox-swagger-ui</artifactId>
  19. <version>2.9.0</version>
  20. </dependency>

1.编写swagger配置类。

  1. /**
  2. * swagger配置类
  3. * @author oKong
  4. *
  5. */
  6. @EnableSwagger2
  7. @Configuration
  8. public class SwaggerConfig {
  9. //是否开启swagger,正式环境一般是需要关闭的,可根据springboot的多环境配置进行设置
  10. @Value(value = "${swagger.enabled}")
  11. Boolean swaggerEnabled;
  12. @Bean
  13. public Docket createRestApi() {
  14. return new Docket(DocumentationType.SWAGGER_2).apiInfo(apiInfo())
  15. // 是否开启
  16. .enable(swaggerEnabled).select()
  17. // 扫描的路径包
  18. .apis(RequestHandlerSelectors.basePackage("cn.lqdev.learning.springcloud.zuul.service"))
  19. // 指定路径处理PathSelectors.any()代表所有的路径
  20. .paths(PathSelectors.any()).build().pathMapping("/");
  21. }
  22. //设置api信息
  23. private ApiInfo apiInfo() {
  24. return new ApiInfoBuilder()
  25. .title("路由网关(Zuul):利用swagger2聚合API文档-service-one")
  26. .description("oKong | 趔趄的猿")
  27. // 作者信息
  28. .contact(new Contact("oKong", "https://blog.lqdev.cn/", "499452441@qq.com"))
  29. .version("1.0.0")
  30. .build();
  31. }
  32. }

2.编写控制层,设置对外api服务信息,同时创建了请求响应的实体类。

DemoController.java

  1. /**
  2. * demo示例
  3. * @author oKong
  4. *
  5. */
  6. @RestController
  7. @Api(tags="servicie-one服务")
  8. @Slf4j
  9. public class DemoController {
  10. @GetMapping("/hello")
  11. @ApiOperation(value="demo示例")
  12. public DemoResp hello(DemoReq demoReq) {
  13. log.info("DemoReq:{}", demoReq);
  14. return DemoResp.builder()
  15. .code(demoReq.getCode())
  16. .name(demoReq.getName())
  17. .remark(demoReq.getRemark())
  18. .build();
  19. }
  20. }

DemoReq.java

  1. /**
  2. * 请求实体
  3. * @author oKong
  4. *
  5. */
  6. @Data
  7. @Builder
  8. @NoArgsConstructor
  9. @AllArgsConstructor
  10. @ApiModel
  11. public class DemoReq {
  12. @ApiModelProperty(name="code",value="编码",example="oKong")
  13. String code;
  14. @ApiModelProperty(name="name",value="名称",example="趔趄的猿")
  15. String name;
  16. @ApiModelProperty(name="remark",value="备注",example="blog:blog.lqdev.cn")
  17. String remark;
  18. }

DemoResp.java

  1. /**
  2. * 响应实体
  3. * @author Okong
  4. *
  5. */
  6. @Data
  7. @Builder
  8. @NoArgsConstructor
  9. @AllArgsConstructor
  10. @ApiModel
  11. public class DemoResp {
  12. @ApiModelProperty(name="code",value="编码",example="oKong")
  13. String code;
  14. @ApiModelProperty(name="name",value="名称",example="趔趄的猿")
  15. String name;
  16. @ApiModelProperty(name="remark",value="备注",example="blog:blog.lqdev.cn")
  17. String remark;
  18. }

3.编写启动类。

  1. /**
  2. * api服务1 示例
  3. * @author oKong
  4. *
  5. */
  6. @SpringBootApplication
  7. @EnableDiscoveryClient
  8. @Slf4j
  9. public class ServiceOneApplication {
  10. public static void main(String[] args) throws Exception {
  11. SpringApplication.run(ServiceOneApplication.class, args);
  12. log.info("spring-cloud-zuul-service-one启动!");
  13. }
  14. }

4.添加配置信息。

  1. spring.application.name=api-service-one
  2. server.port=789
  3. # 注册中心地址 -此为单机模式
  4. eureka.client.service-url.defaultZone=http://127.0.0.1:1000/eureka
  5. # 启用ip配置 这样在注册中心列表中看见的是以ip+端口呈现的
  6. eureka.instance.prefer-ip-address=true
  7. # 实例名称 最后呈现地址:ip:2000
  8. eureka.instance.instance-id=${spring.cloud.client.ip-address}:${server.port}
  9. # swagger开关
  10. swagger.enabled=true

5.启动应用,访问:http://127.0.0.1:789/swagger-ui.html 就可以单应用api文档配置成功了

路由网关端

创建项目:spring-cloud-zuul-gateway

关于zuul的使用,可以查看:第九章:路由网关(Zuul)的使用

0.引入相关依赖。

  1. <!-- zuul 依赖 -->
  2. <dependency>
  3. <groupId>org.springframework.cloud</groupId>
  4. <artifactId>spring-cloud-starter-netflix-zuul</artifactId>
  5. </dependency>
  6. <!-- 客户端依赖 -->
  7. <dependency>
  8. <groupId>org.springframework.cloud</groupId>
  9. <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
  10. </dependency>
  11. <!--swagger -->
  12. <dependency>
  13. <groupId>io.springfox</groupId>
  14. <artifactId>springfox-swagger2</artifactId>
  15. <version>2.9.0</version>
  16. </dependency>
  17. <dependency>
  18. <groupId>io.springfox</groupId>
  19. <artifactId>springfox-swagger-ui</artifactId>
  20. <version>2.9.0</version>
  21. </dependency>

1.添加相关配置信息。

  1. spring.application.name=zuul-gateway
  2. server.port=8899
  3. # 注册中心地址 -此为单机模式
  4. eureka.client.service-url.defaultZone=http://127.0.0.1:1000/eureka
  5. # 启用ip配置 这样在注册中心列表中看见的是以ip+端口呈现的
  6. eureka.instance.prefer-ip-address=true
  7. # 实例名称 最后呈现地址:ip:15678
  8. eureka.instance.instance-id=${spring.cloud.client.ip-address}:${server.port}
  9. # swagger开启开关
  10. swagger.enabled=true

2.编写swagger配置类(重点)

  1. @EnableSwagger2
  2. @Configuration
  3. @Primary //多个bean时 此类优先使用
  4. public class SwaggerConfig implements SwaggerResourcesProvider{
  5. //是否开启swagger,正式环境一般是需要关闭的,可根据springboot的多环境配置进行设置
  6. @Value(value = "${swagger.enabled}")
  7. Boolean swaggerEnabled;
  8. @Autowired
  9. RouteLocator routeLocator;
  10. @Bean
  11. public Docket createRestApi() {
  12. return new Docket(DocumentationType.SWAGGER_2).apiInfo(apiInfo())
  13. // 是否开启
  14. .enable(swaggerEnabled).select()
  15. // 扫描的路径包
  16. .apis(RequestHandlerSelectors.basePackage("cn.lqdev.learning.springcloud.zuul.swagger2"))
  17. // 指定路径处理PathSelectors.any()代表所有的路径
  18. .paths(PathSelectors.any()).build().pathMapping("/");
  19. }
  20. //设置api信息
  21. private ApiInfo apiInfo() {
  22. return new ApiInfoBuilder()
  23. .title("路由网关(Zuul):利用swagger2聚合API文档")
  24. .description("oKong | 趔趄的猿")
  25. // 作者信息
  26. .contact(new Contact("oKong", "https://blog.lqdev.cn/", "499452441@qq.com"))
  27. .version("1.0.0")
  28. .termsOfServiceUrl("https://github.com/xie19900123/")
  29. .build();
  30. }
  31. @Override
  32. public List<SwaggerResource> get() {
  33. //利用routeLocator动态引入微服务
  34. List<SwaggerResource> resources = new ArrayList<>();
  35. resources.add(swaggerResource("zuul-gateway","/v2/api-docs","1.0"));
  36. //循环 使用Lambda表达式简化代码
  37. routeLocator.getRoutes().forEach(route ->{
  38. //动态获取
  39. resources.add(swaggerResource(route.getId(),route.getFullPath().replace("**", "v2/api-docs"), "1.0"));
  40. });
  41. //也可以直接 继承 Consumer接口
  42. // routeLocator.getRoutes().forEach(new Consumer<Route>() {
  43. //
  44. // @Override
  45. // public void accept(Route t) {
  46. // // TODO Auto-generated method stub
  47. //
  48. // }
  49. // });
  50. return resources;
  51. }
  52. private SwaggerResource swaggerResource(String name,String location, String version) {
  53. SwaggerResource swaggerResource = new SwaggerResource();
  54. swaggerResource.setName(name);
  55. swaggerResource.setLocation(location);
  56. swaggerResource.setSwaggerVersion(version);
  57. return swaggerResource;
  58. }
  59. }

这里继承SwaggerResourcesProvider接口是实现聚合api的关键,另外通过RouteLocator类获取路由列表是实现自动聚合的关键。

当然,这里也是可以手动进行添加的。

3.编写zuul内部控制层。

  1. /**
  2. * zuul 内部提供对外服务示例
  3. * @author oKong
  4. *
  5. */
  6. @RestController
  7. @RequestMapping("/demo")
  8. @Api(tags="zuul内部rest api")
  9. public class DemoController {
  10. @GetMapping("/hello")
  11. @ApiOperation(value="demo示例",notes="demo示例")
  12. @ApiImplicitParam(name="name",value="名称",example="oKong")
  13. public String hello(String name) {
  14. return "hi," + name + ",this is zuul api! ";
  15. }
  16. }

4.编写启动类。

  1. /**
  2. * zuul使用swagger2聚合微服务api示例
  3. * @author oKong
  4. *
  5. */
  6. @SpringBootApplication
  7. @EnableZuulProxy
  8. @EnableDiscoveryClient
  9. @Slf4j
  10. public class ZuulSwaggerApplication {
  11. public static void main(String[] args) throws Exception {
  12. SpringApplication.run(ZuulSwaggerApplication.class, args);
  13. log.info("spring-cloud-zuul-gateway启动!");
  14. }
  15. }

5.启动应用,访问:http://127.0.0.1:8899/swagger-ui.html 可以看见页面显示的是网关项目的swagger文档信息。

现在看看右上角的Select a spec下拉框,可以看见下拉框中包含了注册中心下的所有微服务了。

此时,我们切换下api-service-one,可以看见api-service-one的api列表了。

切换到api-service-two,也可以看见都要的api列表信息。

参考资料

  1. https://piotrminkowski.wordpress.com/2017/04/14/microservices-api-documentation-with-swagger2/

总结

本章节主要简单介绍了如何在Zuul路由网关服务利用Swagger2进行微服务api的聚合功能。这样查看各微服务的api文档就很方便,集中,不需要在切换不同文档地址了。

最后

目前互联网上大佬都有分享SpringCloud系列教程,内容可能会类似,望多多包涵了。原创不易,码字不易,还希望大家多多支持。若文中有错误之处,还望提出,谢谢。

老生常谈

  • 个人QQ:499452441
  • 微信公众号:lqdevOps

个人博客:http://blog.lqdev.cn

源码示例:https://github.com/xie19900123/spring-cloud-learning

以下教程可能你会感兴趣:

原文地址:https://blog.lqdev.cn/2018/10/19/SpringCloud/chapter-eleven/

白话SpringCloud | 第十一章:路由网关(Zuul):利用swagger2聚合API文档的更多相关文章

  1. 白话SpringCloud | 第十章:路由网关(Zuul)进阶:过滤器、异常处理

    前言 简单介绍了关于Zuul的一些简单使用以及一些路由规则的简单说明.而对于一个统一网关而言,需要处理各种各类的请求,对不同的url进行拦截,或者对调用服务的异常进行二次处理等等.今天,我们就来了解下 ...

  2. SpringCloud学习系列之六 ----- 路由网关Zuul基础使用教程

    前言 在上篇中介绍了SpringCloud Config的完美使用版本,本篇则介绍基于SpringCloud(基于SpringBoot2.x,.SpringCloud Finchley版)中的路由网关 ...

  3. 玩转SpringCloud(F版本) 四.路由网关(zuul)

    本篇文章基于: 01)玩转SpringCloud 一.服务的注册与发现(Eureka) 02) 玩转SpringCloud 二.服务消费者(1)ribbon+restTemplate 03) 玩转Sp ...

  4. 白话SpringCloud | 第零章:前言

    说在前面 大清早醒来,觉得睡不着了.还是起来,写写博客.但最后发现关于SpringBoot的安全相关的还是比较多内容的,也比较专业,怕是一个多小时完不成的,也罢,那就来写写关于SpringCloud前 ...

  5. 白话SpringCloud | 第九章:路由网关(Zuul)的使用

    前言 介绍完分布式配置中心,结合前面的文章.我们已经有了一个微服务的框架了,可以对外提供api接口服务了.但现在试想一下,在微服务框架中,每个对外服务都是独立部署的,对外的api或者服务地址都不是不尽 ...

  6. SpringCloud(5)路由网关Spring Cloud Zuul

    一个简单的微服务系统如下图: 1.为什么需要Zuul Zuul很容易实现 负载均衡.智能路由 和 熔断器,可以做身份认证和权限认证,可以实现监控,在高流量状态下,对服务进行降级. 2.路由网关 继续前 ...

  7. springcloud(十一):服务网关Zuul高级篇

    时间过的很快,写springcloud(十):服务网关zuul初级篇还在半年前,现在已经是2018年了,我们继续探讨Zuul更高级的使用方式. 上篇文章主要介绍了Zuul网关使用模式,以及自动转发机制 ...

  8. springCloud之路API路由网关Zuul

    1.简介 简单的理解就是,相当于在所有服务的调用前加了一层防火墙, 主要就是对外提供服务接口的时候,起到了请求的路由和过滤作用,也因此能够隐藏内部服务的接口细节,提高系统的安全性: 官方文档:http ...

  9. 跟我学SpringCloud | 第九篇:服务网关Zuul初

    SpringCloud系列教程 | 第九篇:服务网关Zuul初探 前面的文章我们介绍了,Eureka用于服务的注册于发现,Feign支持服务的调用以及均衡负载,Hystrix处理服务的熔断防止故障扩散 ...

随机推荐

  1. 《C#多线程编程实战》2.10 SpinWait

    emmm 这个SpinWait 中文是自旋等待的意思. 所谓自旋,就是自己追自己影子,周伯通的左右手互博,不好听就是放屁自己追着玩,小狗转圈咬自己的尾巴 SpinWait是一个结构体,并不是一个类. ...

  2. App Store提交审核报错 ERROR ITMS-90087解决办法

    1.原因说明 app对Wifi进行配网, 使用了GizWifiSDK.framework提交App Store时候报错了 App Store Connect Operation Error ERROR ...

  3. windows查看和杀死占用端口的进程

    1.首先使用 netstat -ano查看占用端口的进程号 2.然后使用 taskkill /PID (进程号)杀死进程

  4. 2018数学建模A题优秀论文:高温作业专用服装设计

    高温作业专用服装设计 摘 要 本文针对多层材料的高温作业服装的传热问题进行研究,综合考虑多种传热方式建立传热模型,并以此模型为基础解决了服装设计中各层材料最佳厚度的问题. 对于问题一,要求在热物性系数 ...

  5. request payload

    最近在调试代码时发现有Request Payload的情况,从网上查一些文件,也都有较多的描述.下面我只是说明一下大家没有注意的地方 关于HTTP请求,都是通过URL及参数向后台发送数据.主要方式有G ...

  6. Udp -内部缓冲区

    1.每个socket关联了两个缓冲区,一个用于发送,一个用于接收. 2. 3.发送:(1)sendto()把数据放在sendbuf(缓冲区),通知os来取 (2)os在适当的时候过来取数据,并发到网络 ...

  7. c#优秀文章

    文件传输示例]C# WinForm WebSocket (非浏览器):http://bbs.cskin.net/thread-4431-1-1.html NanUI for Winform发布,让Wi ...

  8. js 封装一个均速动画函数

    //动画函数---任意一个元素移动到指定的目标位置 //element为元素 target为位置 function carToon(element, target) { //设置一个定时器让他循环去增 ...

  9. 获取一个表中的字段总数(mysql) Navicat如何导出Excel格式表结构 获取某个库中的一个表中的所有字段和数据类型

    如何获取一个表中的字段总数 1.function show columns from 表明: 结果 : 2.functiuon select count(*) from INFORMATION_SCH ...

  10. 队列 和 堆栈用python 来实现

    一.利用python列表实现堆栈和队列 堆栈: 堆栈是一个后进先出的数据结构,其工作方式就像生活中常见到的直梯,先进去的人肯定是最后出. 我们可以设置一个类,用列表来存放栈中的元素的信息,利用列表的a ...