SpringCloud Alibaba微服务实战十一 - Swagger接口文档聚合

简介: SpringCloud Alibaba微服务实战十一 - Swagger接口文档聚合

导读:在SpringCloud体系架构中,我们需要的每个服务都需要对外输出接口文档,本篇内容主要是给我们的微服务配上Swagger的接口文档,并在网关层完成接口聚合。


Swagger2简介


在当下很多项目都会采用前后端分离的模式,前端和后端的工作由不同的开发人员完成。在这种开发模式下,我们需要维护一份及时更新且完整的Rest API接口文档。传统意义上的文档都是后端人员在开发相关接口后手动更新到接口文档上,但是这种方式很难保证文档的及时性,而且由于一些原因后端开发人员可能会忘记更新,这样就会导致随着开发的进行接口文档会失去他本身的参考意义,反而会增加沟通成本。而 Swagger 给我们提供了一个全新的维护 API 文档的方式,他有以下几个作用:

  • 只需要后端开发人员给接口加上几个注解,Swagger就可以根据代码自动生成API文档,节省编写接口文档的工作量,而且对接口修改时只需要修改相应的注解,能保证接口的及时性;
  • SwaggerUI展现出来的是一份可交互式的API文档,我们可以直接在接口页面对功能测试,省去了大量接口联调的时间;

Swagger2有以下几个常见注解,大家在使用过程中会经常用到。


@Api

此注解可以用来标记 Controller 的功能,如:

@Api(tags = "product模块")
publicclass ProductController implements ProductFeign {
}


@ApiOperation

此注解用来标记一个方法的作用

@ApiOperation(value = "根据产品编码查找对应的产品")
public ResultData<ProductDTO> getByCode(@PathVariable String productCode){
  ...
}


@ApilmplicitParam@ApilmplicitParams

这组注解用来对参数进行描述,@ApilmplicitParam 有几个重要的参数:name:参数名value:参数的汉字说明、解释required:参数是否必须传paramType:参数放在哪个地方(header:对应@RequestHeader的参数;query :对应@RequestParam的参数;path :对应@PathVariable的参数;body:对应 @RequestBody 的参数;form(普通表单提交)  )

@ApiImplicitParam(name = "productCode",value = "产品编码", required = true,paramType = "path")
public ResultData<ProductDTO> getByCode(@PathVariable String productCode){
  ...
}
@ApiImplicitParam(name = "productCode" , value = "产品编码",required = true, paramType = "query")
public ResultData<String> delete(@RequestParam String productCode){
  ...
}

如果有多个参数,则需要使用@ApilmplicitParams 注解。


@ApiModel@ApiModelProperty

如果参数是一个对象,则需要在对象所在的类上加上此注解。这种一般用在post创建的时候,使用 @RequestBody 这样的场景,请求参数无法使用 @ApiImplicitParam 注解进行描述的时候 。在具体字段上则使用@ApiModelProperty注解。如:

@Data
@ApiModel(value = "产品封装类ProductDTO",description = "产品相关信息封装,用于接口传参")
publicclass ProductDTO {
    @ApiModelProperty(value = "产品主键")
    private Integer id;
    @ApiModelProperty(value = "产品编码")
    private String productCode;
    @ApiModelProperty(value = "产品名称")
    private String productName;
    @ApiModelProperty(value = "数量")
    private Integer count;
    @ApiModelProperty(value = "单价")
    private BigDecimal price;
}


使用


在项目中要使用Swagger2很简单,按照以下几步即可:

  • 在pom文件中引入jar包 每个微服务都需要使用,我们直接将其引入在cloud-common服务中
<!--swagger2-->
<dependency>
  <groupId>io.springfox</groupId>
  <artifactId>springfox-swagger2</artifactId>
    <version>2.9.2</version>
</dependency>
<dependency>
  <groupId>io.springfox</groupId>
  <artifactId>springfox-swagger-ui</artifactId>
    <version>2.9.2</version>
</dependency>
  • 在微服务中编写swagger2的配置类SwaggerConfig
@Configuration
@EnableSwagger2
publicclass SwaggerConfig {
    privatestaticfinal String VERSION = "1.0.0";
    /**
     * 创建API
     */
    @Bean
    public Docket createRestApi(){
        returnnew Docket(DocumentationType.SWAGGER_2)
                .apiInfo(apiInfo())
                .select()
                //指定接口包所在路径
                .apis(RequestHandlerSelectors.basePackage("com.javadaily.product.controller"))
                .paths(PathSelectors.any())
                .build();
    }
    /**
     * 添加摘要信息
     */
    private ApiInfo apiInfo() {
        returnnew ApiInfoBuilder()
                .title("product-server接口文档")
                .contact(new Contact("JAVA日知录","http://javadaily.cn","jianzh5@163.com"))
                .description("product-server接口文档")
                .termsOfServiceUrl("http://javadaily.cn")
                .license("The Apache License, Version 2.0")
                .licenseUrl("http://www.apache.org/licenses/LICENSE-2.0.html")
                .version(VERSION)
                .build();
    }
}

.apis方法用于指定生成注解的范围,有以下四种取值逻辑RequestHandlerSelectors.any(),为所有接口都生成API文档,这种方式不必在接口上加任何注解,但是生成的文档没有任何注释,可读性不高;

RequestHandlerSelectors.basePackage(xx.xx),为指定包下的controller生成接口文档

RequestHandlerSelectors.withClassAnnotation(Api.class),为有@api注解的接口生成api文档

RequestHandlerSelectors.withMethodAnnotation(ApiOperation.class),为有@ApiOperation注解的方法生成API文档。

  • 给相关接口加上Swagger的注解 注解的详细说明参见上文。
  • 打开swagger2接口API页面http://localhost:8020/swagger-ui.html

网关聚合


我们已经给各个微服务加上了api文档,但是每次都需要分别输入各个微服务的文档地址,不太方便。本节内容主要是将各个微服务的api地址聚合到网关层,打开网关的api地址即可查看其它所有服务的接口文档,效果如下:

实现步骤如下:

  • 编写配置类实现 SwaggerResourcesProvider 接口聚合其他微服务的api资源
@Component
@AllArgsConstructor
publicclass CustomSwaggerResourceProvider implements SwaggerResourcesProvider {
    /**
     * Swagger2默认的url后缀
     */
    publicstaticfinal String SWAGGER2URL = "/v2/api-docs";
    /**
     * 网关路由
     */
    privatefinal RouteLocator routeLocator;
    privatefinal GatewayProperties gatewayProperties;
    /**
     * 聚合其他服务接口
     * @return
     */
    @Override
    public List<SwaggerResource> get() {
        List<SwaggerResource> resourceList = new ArrayList<>();
        List<String> routes = new ArrayList<>();
        //获取网关中配置的route
        routeLocator.getRoutes().subscribe(route -> routes.add(route.getId()));
        gatewayProperties.getRoutes().stream().filter(routeDefinition -> routes.contains(routeDefinition.getId()))
                .forEach(routeDefinition -> routeDefinition.getPredicates().stream()
                .filter(predicateDefinition -> "Path".equalsIgnoreCase(predicateDefinition.getName()))
                .forEach(predicateDefinition -> resourceList.add(
                            swaggerResource(
                                routeDefinition.getId(),
                                predicateDefinition
                                        .getArgs()
                                        .get(NameUtils.GENERATED_NAME_PREFIX + "0")
                                        .replace("/**",SWAGGER2URL)
//这里拼接时需要注意
//网关配置account映射到account-service,要么将网关的配置修改成account-service映射成account-service
//要么就在这个拼接处解决
                        )
                )));
        return resourceList;
    }
    private SwaggerResource swaggerResource(String name, String location) {
        SwaggerResource swaggerResource = new SwaggerResource();
        swaggerResource.setName(name);
        swaggerResource.setLocation(location);
        swaggerResource.setSwaggerVersion("2.0");
        return swaggerResource;
    }
}
  • 自定义Rest接口
@RestController
@RequestMapping("/swagger-resources")
publicclass SwaggerHandler {
    @Autowired(required = false)
    private SecurityConfiguration securityConfiguration;
    @Autowired(required = false)
    private UiConfiguration uiConfiguration;
    privatefinal SwaggerResourcesProvider swaggerResources;
    @Autowired
    public SwaggerHandler(SwaggerResourcesProvider swaggerResources) {
        this.swaggerResources = swaggerResources;
    }
    @GetMapping("/configuration/security")
    public Mono<ResponseEntity<SecurityConfiguration>> securityConfiguration() {
        return Mono.just(new ResponseEntity<>(
                Optional.ofNullable(securityConfiguration).orElse(SecurityConfigurationBuilder.builder().build()), HttpStatus.OK));
    }
    @GetMapping("/configuration/ui")
    public Mono<ResponseEntity<UiConfiguration>> uiConfiguration() {
        return Mono.just(new ResponseEntity<>(
                Optional.ofNullable(uiConfiguration).orElse(UiConfigurationBuilder.builder().build()),HttpStatus.OK));
    }
    @GetMapping("")
    public Mono<ResponseEntity> swaggerResources() {
        return Mono.just((new ResponseEntity<>(swaggerResources.get(), HttpStatus.OK)));
    }
}

好了,各位朋友们,本期的内容到此就全部结束啦,能看到这里的同学都是优秀的同学,下一个升职加薪的就是你了!

目录
相关文章
|
11天前
|
Dubbo Java 应用服务中间件
Spring Cloud Dubbo:微服务通信的高效解决方案
【10月更文挑战第15天】随着信息技术的发展,微服务架构成为企业应用开发的主流。Spring Cloud Dubbo结合了Dubbo的高性能RPC和Spring Cloud的生态系统,提供高效、稳定的微服务通信解决方案。它支持多种通信协议,具备服务注册与发现、负载均衡及容错机制,简化了服务调用的复杂性,使开发者能更专注于业务逻辑的实现。
30 2
|
11天前
|
JSON Java 数据格式
【微服务】SpringCloud之Feign远程调用
本文介绍了使用Feign作为HTTP客户端替代RestTemplate进行远程调用的优势及具体使用方法。Feign通过声明式接口简化了HTTP请求的发送,提高了代码的可读性和维护性。文章详细描述了Feign的搭建步骤,包括引入依赖、添加注解、编写FeignClient接口和调用代码,并提供了自定义配置的示例,如修改日志级别等。
30 1
|
14天前
|
人工智能 文字识别 Java
SpringCloud+Python 混合微服务,如何打造AI分布式业务应用的技术底层?
尼恩,一位拥有20年架构经验的老架构师,通过其深厚的架构功力,成功指导了一位9年经验的网易工程师转型为大模型架构师,薪资逆涨50%,年薪近80W。尼恩的指导不仅帮助这位工程师在一年内成为大模型架构师,还让他管理起了10人团队,产品成功应用于多家大中型企业。尼恩因此决定编写《LLM大模型学习圣经》系列,帮助更多人掌握大模型架构,实现职业跃迁。该系列包括《从0到1吃透Transformer技术底座》、《从0到1精通RAG架构》等,旨在系统化、体系化地讲解大模型技术,助力读者实现“offer直提”。此外,尼恩还分享了多个技术圣经,如《NIO圣经》、《Docker圣经》等,帮助读者深入理解核心技术。
SpringCloud+Python 混合微服务,如何打造AI分布式业务应用的技术底层?
|
2月前
|
安全 应用服务中间件 API
微服务分布式系统架构之zookeeper与dubbo-2
微服务分布式系统架构之zookeeper与dubbo-2
|
2月前
|
负载均衡 Java 应用服务中间件
微服务分布式系统架构之zookeeper与dubbor-1
微服务分布式系统架构之zookeeper与dubbor-1
|
3月前
|
Kubernetes Cloud Native Docker
云原生之旅:从容器到微服务的架构演变
【8月更文挑战第29天】在数字化时代的浪潮下,云原生技术以其灵活性、可扩展性和弹性管理成为企业数字化转型的关键。本文将通过浅显易懂的语言和生动的比喻,带领读者了解云原生的基本概念,探索容器化技术的奥秘,并深入微服务架构的世界。我们将一起见证代码如何转化为现实中的服务,实现快速迭代和高效部署。无论你是初学者还是有经验的开发者,这篇文章都会为你打开一扇通往云原生世界的大门。
|
3月前
|
负载均衡 应用服务中间件 持续交付
微服务架构下的Web服务器部署
【8月更文第28天】随着互联网应用的不断发展,传统的单体应用架构逐渐显露出其局限性,特别是在可扩展性和维护性方面。为了解决这些问题,微服务架构应运而生。微服务架构通过将应用程序分解成一系列小型、独立的服务来提高系统的灵活性和可维护性。本文将探讨如何在微服务架构中有效部署和管理Web服务器实例,并提供一些实际的代码示例。
98 0
|
22天前
|
Kubernetes 安全 微服务
使用 Istio 缓解电信 5G IoT 微服务 Pod 架构的安全挑战
使用 Istio 缓解电信 5G IoT 微服务 Pod 架构的安全挑战
42 8
|
26天前
|
消息中间件 负载均衡 Cloud Native
云原生之旅:从容器到微服务的架构演变
在数字化转型的风潮中,云原生技术以其灵活性、可扩展性和弹性而备受青睐。本文将通过一个虚拟的故事,讲述一个企业如何逐步拥抱云原生,实现从传统架构向容器化和微服务架构的转变,以及这一过程中遇到的挑战和解决方案。我们将以浅显易懂的方式,探讨云原生的核心概念,并通过实际代码示例,展示如何在云平台上部署和管理微服务。
|
2月前
|
运维 Cloud Native Devops
云原生架构的崛起与实践云原生架构是一种通过容器化、微服务和DevOps等技术手段,帮助应用系统实现敏捷部署、弹性扩展和高效运维的技术理念。本文将探讨云原生的概念、核心技术以及其在企业中的应用实践,揭示云原生如何成为现代软件开发和运营的主流方式。##
云原生架构是现代IT领域的一场革命,它依托于容器化、微服务和DevOps等核心技术,旨在解决传统架构在应对复杂业务需求时的不足。通过采用云原生方法,企业可以实现敏捷部署、弹性扩展和高效运维,从而大幅提升开发效率和系统可靠性。本文详细阐述了云原生的核心概念、主要技术和实际应用案例,并探讨了企业在实施云原生过程中的挑战与解决方案。无论是正在转型的传统企业,还是寻求创新的互联网企业,云原生都提供了一条实现高效能、高灵活性和高可靠性的技术路径。 ##
151 3

热门文章

最新文章