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

前言

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

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

  • Zuul聚合示例

    • 微服务端
    • 路由网关端
  • 参考资料
  • 总结
  • 最后
  • 老生常谈

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.引入相关依赖

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <!-- 客户端依赖 -->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
        </dependency>
        <!--swagger -->
        <dependency>
            <groupId>io.springfox</groupId>
            <artifactId>springfox-swagger2</artifactId>
            <version>2.9.0</version>
        </dependency>
        <dependency>
            <groupId>io.springfox</groupId>
            <artifactId>springfox-swagger-ui</artifactId>
            <version>2.9.0</version>
        </dependency> 

1.编写swagger配置类。

/**
 * swagger配置类
 * @author oKong
 *
 */
@EnableSwagger2
@Configuration
public class SwaggerConfig {

    //是否开启swagger,正式环境一般是需要关闭的,可根据springboot的多环境配置进行设置
    @Value(value = "${swagger.enabled}")
    Boolean swaggerEnabled;

    @Bean
    public Docket createRestApi() {
        return new Docket(DocumentationType.SWAGGER_2).apiInfo(apiInfo())
                // 是否开启
                .enable(swaggerEnabled).select()
                // 扫描的路径包
                .apis(RequestHandlerSelectors.basePackage("cn.lqdev.learning.springcloud.zuul.service"))
                // 指定路径处理PathSelectors.any()代表所有的路径
                .paths(PathSelectors.any()).build().pathMapping("/");
    }

    //设置api信息
    private ApiInfo apiInfo() {
        return new ApiInfoBuilder()
                .title("路由网关(Zuul):利用swagger2聚合API文档-service-one")
                .description("oKong | 趔趄的猿")
                // 作者信息
                .contact(new Contact("oKong", "https://blog.lqdev.cn/", "[email protected]"))
                .version("1.0.0")
                .build();
    }
}

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

DemoController.java

/**
 * demo示例
 * @author oKong
 *
 */
@RestController
@Api(tags="servicie-one服务")
@Slf4j
public class DemoController {

    @GetMapping("/hello")
    @ApiOperation(value="demo示例")
    public DemoResp hello(DemoReq demoReq) {
        log.info("DemoReq:{}", demoReq);

        return DemoResp.builder()
                .code(demoReq.getCode())
                .name(demoReq.getName())
                .remark(demoReq.getRemark())
                .build();
    }
}

DemoReq.java

/**
 * 请求实体
 * @author oKong
 *
 */
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
@ApiModel
public class DemoReq {

    @ApiModelProperty(name="code",value="编码",example="oKong")
    String code;

    @ApiModelProperty(name="name",value="名称",example="趔趄的猿")
    String name;

    @ApiModelProperty(name="remark",value="备注",example="blog:blog.lqdev.cn")
    String remark;
}

DemoResp.java

/**
 * 响应实体
 * @author Okong
 *
 */
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
@ApiModel
public class DemoResp {

    @ApiModelProperty(name="code",value="编码",example="oKong")
    String code;

    @ApiModelProperty(name="name",value="名称",example="趔趄的猿")
    String name;

    @ApiModelProperty(name="remark",value="备注",example="blog:blog.lqdev.cn")
    String remark;
}

3.编写启动类。

/**
 * api服务1 示例
 * @author oKong
 *
 */
@SpringBootApplication
@EnableDiscoveryClient
@Slf4j
public class ServiceOneApplication {

    public static void main(String[] args) throws Exception {
        SpringApplication.run(ServiceOneApplication.class, args);
        log.info("spring-cloud-zuul-service-one启动!");
    }
}

4.添加配置信息。

spring.application.name=api-service-one
server.port=789

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

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

路由网关端

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

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

0.引入相关依赖。

        <!-- zuul 依赖 -->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-zuul</artifactId>
        </dependency>
        <!-- 客户端依赖 -->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
        </dependency>
        <!--swagger -->
        <dependency>
            <groupId>io.springfox</groupId>
            <artifactId>springfox-swagger2</artifactId>
            <version>2.9.0</version>
        </dependency>
        <dependency>
            <groupId>io.springfox</groupId>
            <artifactId>springfox-swagger-ui</artifactId>
            <version>2.9.0</version>
        </dependency>

1.添加相关配置信息。

spring.application.name=zuul-gateway
server.port=8899

# 注册中心地址 -此为单机模式
eureka.client.service-url.defaultZone=http://127.0.0.1:1000/eureka
# 启用ip配置 这样在注册中心列表中看见的是以ip+端口呈现的
eureka.instance.prefer-ip-address=true
# 实例名称  最后呈现地址:ip:15678
eureka.instance.instance-id=${spring.cloud.client.ip-address}:${server.port}

# swagger开启开关
swagger.enabled=true

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

@EnableSwagger2
@Configuration
@Primary //多个bean时 此类优先使用
public class SwaggerConfig implements SwaggerResourcesProvider{

    //是否开启swagger,正式环境一般是需要关闭的,可根据springboot的多环境配置进行设置
    @Value(value = "${swagger.enabled}")
    Boolean swaggerEnabled;

    @Autowired
    RouteLocator routeLocator;

    @Bean
    public Docket createRestApi() {
        return new Docket(DocumentationType.SWAGGER_2).apiInfo(apiInfo())
                // 是否开启
                .enable(swaggerEnabled).select()
                // 扫描的路径包
                .apis(RequestHandlerSelectors.basePackage("cn.lqdev.learning.springcloud.zuul.swagger2"))
                // 指定路径处理PathSelectors.any()代表所有的路径
                .paths(PathSelectors.any()).build().pathMapping("/");
    }

    //设置api信息
    private ApiInfo apiInfo() {
        return new ApiInfoBuilder()
                .title("路由网关(Zuul):利用swagger2聚合API文档")
                .description("oKong | 趔趄的猿")
                // 作者信息
                .contact(new Contact("oKong", "https://blog.lqdev.cn/", "[email protected]"))
                .version("1.0.0")
                .termsOfServiceUrl("https://github.com/xie19900123/")
                .build();
    }

    @Override
    public List<SwaggerResource> get() {
        //利用routeLocator动态引入微服务
        List<SwaggerResource> resources = new ArrayList<>();
        resources.add(swaggerResource("zuul-gateway","/v2/api-docs","1.0"));
        //循环 使用Lambda表达式简化代码
        routeLocator.getRoutes().forEach(route ->{
            //动态获取
            resources.add(swaggerResource(route.getId(),route.getFullPath().replace("**", "v2/api-docs"), "1.0"));
        });
        //也可以直接 继承 Consumer接口
//      routeLocator.getRoutes().forEach(new Consumer<Route>() {
//
//          @Override
//          public void accept(Route t) {
//              // TODO Auto-generated method stub
//
//          }
//      });
        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;
    }
}

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

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

3.编写zuul内部控制层。

/**
 * zuul 内部提供对外服务示例
 * @author oKong
 *
 */
@RestController
@RequestMapping("/demo")
@Api(tags="zuul内部rest api")
public class DemoController {

    @GetMapping("/hello")
    @ApiOperation(value="demo示例",notes="demo示例")
    @ApiImplicitParam(name="name",value="名称",example="oKong")
    public String hello(String name) {
        return "hi," + name + ",this is zuul api! ";
    }
}

4.编写启动类。

/**
 * zuul使用swagger2聚合微服务api示例
 * @author oKong
 *
 */
@SpringBootApplication
@EnableZuulProxy
@EnableDiscoveryClient
@Slf4j
public class ZuulSwaggerApplication {
    public static void main(String[] args) throws Exception {
        SpringApplication.run(ZuulSwaggerApplication.class, args);
        log.info("spring-cloud-zuul-gateway启动!");
    }
}

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/

原文地址:https://www.cnblogs.com/okong/p/springcloud-eleven.html

时间: 2024-11-02 23:40:39

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

企业级 SpringCloud (五)路由网关(zuul)

在微服务架构中,需要几个基础的服务治理组件,包括服务注册与发现.服务消费.负载均衡.断路器.智能路由.配置管理等,由这几个基础组件相互协作,共同组建了一个简单的微服务系统.一个简答的微服务系统如下图: Azure (1).png 注意:A服务和B服务是可以相互调用的,作图的时候忘记了.并且配置服务也是注册到服务注册中心的. 在Spring Cloud微服务系统中,一种常见的负载均衡方式是,客户端的请求首先经过负载均衡(zuul.Ngnix),再到达服务网关(zuul集群),然后再到具体的服.,服

SpringCloud分布式微服务云架构 第五篇: 路由网关(zuul)(Finchley版本)

SpringCloud分布式微服务云架构 第五篇: 路由网关(zuul)(Finchley版本)在微服务架构中,需要几个基础的服务治理组件,包括服务注册与发现.服务消费.负载均衡.断路器.智能路由.配置管理等,了解springcloud架构可以加求求:三五三六二四七二五九,由这几个基础组件相互协作,共同组建了一个简单的微服务系统.一个简答的微服务系统如下图: 注意:A服务和B服务是可以相互调用的,并且配置服务也是注册到服务注册中心的. 在Spring Cloud微服务系统中,一种常见的负载均衡方

SpringCloud路由网关Zuul

什么是网关 Zuul的主要功能是路由转发和过滤器.路由功能是微服务的一部分,比如/api/user转发到到user服务,/api/shop转发到到shop服务.zuul默认和Ribbon结合实现了负载均衡的功能, 类似于nginx转发. 依赖 <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId>

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

SpringCloud系列教程 | 第九篇:服务网关Zuul初探 前面的文章我们介绍了,Eureka用于服务的注册于发现,Feign支持服务的调用以及均衡负载,Hystrix处理服务的熔断防止故障扩散,Spring Cloud Config服务集群配置中心,似乎一个微服务框架已经完成了. 我们还是少考虑了一个问题,外部的应用如何来访问内部各种各样的微服务呢?在微服务架构中,后端服务往往不直接开放给调用端,而是通过一个API网关根据请求的url,路由到相应的服务.当添加API网关后,在第三方调用端

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

本文不涉及技术,只是单纯的一个小技巧. 阅读本文前,你需要对spring-cloud-zuul.spring-cloud-eureka.以及swagger的配置和使用有所了解. 如果你的系统也是用zuul作为分布式系统的网关,同时使用swagger生成文档,想把整个系统的文档整合在同一个页面上,可以参考本文. 项目结构eureka-server:eureka服务注册中心,端口8080, zuul-server:zuul网关,端口8081 payment-server:支付系统,端口8082 or

业余草 SpringCloud教程 | 第五篇: 路由网关(zuul)(Finchley版本)

在微服务架构中,需要几个基础的服务治理组件,包括服务注册与发现.服务消费.负载均衡.断路器.智能路由.配置管理等,由这几个基础组件相互协作,共同组建了一个简单的微服务系统.一个简答的微服务系统如下图:  注意:A服务和B服务是可以相互调用的,作图的时候忘记了.并且配置服务也是注册到服务注册中心的. 在Spring Cloud微服务系统中,一种常见的负载均衡方式是,客户端的请求首先经过负载均衡(zuul.Ngnix),再到达服务网关(zuul集群),然后再到具体的服.,服务统一注册到高可用的服务注

史上最简单的SpringCloud教程 | 第五篇: 路由网关(zuul)(Finchley版本)

在微服务架构中,需要几个基础的服务治理组件,包括服务注册与发现.服务消费.负载均衡.断路器.智能路由.配置管理等,由这几个基础组件相互协作,共同组建了一个简单的微服务系统.一个简答的微服务系统如下图: 注意:A服务和B服务是可以相互调用的,作图的时候忘记了.并且配置服务也是注册到服务注册中心的. 在Spring Cloud微服务系统中,一种常见的负载均衡方式是,客户端的请求首先经过负载均衡(zuul.Ngnix),再到达服务网关(zuul集群),然后再到具体的服.,服务统一注册到高可用的服务注册

SpringCloud (Finchley版本)教程(五):路由网关(zuul)

在微服务架构中,需要几个基础的服务治理组件,包括服务注册与发现.服务消费.负载均衡.断路器.智能路由.配置管理等,由这几个基础组件相互协作,共同组建了一个简单的微服务系统. 注意:A服务和B服务是可以相互调用的,作图的时候忘记了.并且配置服务也是注册到服务注册中心的. 在Spring Cloud微服务系统中,一种常见的负载均衡方式是,客户端的请求首先经过负载均衡(zuul.Ngnix),再到达服务网关(zuul集群),然后再到具体的服.,服务统一注册到高可用的服务注册中心集群,服务的所有的配置文

SpringCloud之路由网关zuul(五)

在微服务架构中,需要几个基础的服务治理组件,包括服务注册与发现.服务消费.负载均衡.断路器.智能路由.配置管理等,由这几个基础组件相互协作,共同组建了一个简单的微服务系统.一个简答的微服务系统如下图: 注意:A服务和B服务是可以相互调用的,作图的时候忘记了.并且配置服务也是注册到服务注册中心的. 在Spring Cloud微服务系统中,一种常见的负载均衡方式是,客户端的请求首先经过负载均衡(zuul.Ngnix),再到达服务网关(zuul集群),然后再到具体的服.,服务统一注册到高可用的服务注册