SpringBoot集成Swagger3,还想来份离线文档?真酷炫

开发 架构
随着项目架构的演化,前后端分离是不可阻挡的趋势。这种模式的协作在实践的过程中经常会遇到的一个问题就是文档。

 [[397948]]

本文转载自微信公众号「程序新视界」,作者二师兄。转载本文请联系程序新视界公众号。

前言

随着项目架构的演化,前后端分离是不可阻挡的趋势。这种模式的协作在实践的过程中经常会遇到的一个问题就是文档。

在《一位CTO告诉我,项目中至少需要这3类文档》一文我们已经描述了文档的重要性,而接口文档便是其中之一,可以说是必不可少的。

但编写接口文档对开发人员来说是一大难题,而且接口还在不断的变化,还要花费精力去维护接口文档的更新。

既然存在痛点,那么必须会出现解决此痛点的产品,这就是Swagger,目前已经更新到Swagger3版本了。如果你还停留在Swagger2,建议升级到Swagger3,整体UI风格及交互友好了不少。

本篇将围绕Swagger3与SpringBoot的集成和离线文档的生成来进行讲解。

Swagger简介

Swagger是一个规范和完整的框架,用于生成、描述、调用和可视化RESTful风格的Web服务。总体目标是使客户端和文件系统作为服务器以同样的速度来更新。文件的方法,参数和模型紧密集成到服务器端的代码,允许API来始终保持同步。

官网:https://swagger.io

Swagger解决的痛点

传统方式提供文档有以下痛点:

  • 接口众多,实现细节复杂,编写文档耗费费力,需要持续维护;
  • 接口文档需要随时进行同步;
  • 接口返回的结果不明确,得构造返回结构体等;
  • 不能直接在线测试接口,通常需要额外的工具,比如PostMan等。

当引入Swagger之后,以上痛点迎刃而解,同时还带来以下优点:

  • 及时性 (接口变更后,前后端人员可实时看到最新版本)
  • 规范性 (接口具体统一风格,如接口地址,请求方式,参数,响应格式和错误信息等)
  • 一致性 (接口信息一致,不会因接口文档版本问题出现分歧)
  • 可测性 (可直接基于接口文档进行测试)

Swagger3的改变

Swagger3.0的改动,官方文档总结如下几点:

  • 删除了对springfox-swagger2的依赖;
  • 删除所有@EnableSwagger2...注解;
  • 添加了springfox-boot-starter依赖项;
  • 移除了guava等第三方依赖;
  • 文档访问地址改为http://ip:port/project/swagger-ui/index.html。

下面就来实战使用一下吧。

SpringBoot集成Swagger3

SpringBoot集成Swagger3与SpringBoot集成其他框架的套路基本一致,通常包括:引入依赖、指定配置文件、创建配置类和使用。

引入依赖

在SpringBoot项目的pom.xml中引入Swagger3依赖:

  1. <dependency> 
  2.     <groupId>io.springfox</groupId> 
  3.     <artifactId>springfox-boot-starter</artifactId> 
  4.     <version>3.0.0</version> 
  5. </dependency> 

 

指定配置文件

通常情况下swagger只能在开发环境或测试环境下开启,生产环境下需要进行关闭的。而swagger的开启与关闭可在application.properties中进行配置:

  1. # 生产环境需设置为false 
  2. springfox.documentation.swagger-ui.enabled=true 

配置类

通过@EnableOpenApi注解启动用Swagger的使用,同时在配置类中对Swagger的通用参数进行配置。

  1. @Configuration 
  2. @EnableOpenApi 
  3. public class Swagger3Config { 
  4.  
  5.     @Bean 
  6.     public Docket createRestApi() { 
  7.         //返回文档摘要信息 
  8.         return new Docket(DocumentationType.OAS_30) 
  9.                 .apiInfo(apiInfo()) 
  10.                 .select() 
  11.                 .apis(RequestHandlerSelectors.withMethodAnnotation(Operation.class)) 
  12.                 .paths(PathSelectors.any()) 
  13.                 .build() 
  14.                 .globalRequestParameters(getGlobalRequestParameters()) 
  15.                 .globalResponses(HttpMethod.GET, getGlobalResponseMessage()) 
  16.                 .globalResponses(HttpMethod.POST, getGlobalResponseMessage()); 
  17.     } 
  18.  
  19.     /** 
  20.      * 生成接口信息,包括标题、联系人等 
  21.      */ 
  22.     private ApiInfo apiInfo() { 
  23.         return new ApiInfoBuilder() 
  24.                 .title("Swagger3接口文档"
  25.                 .description("如有疑问,可联系二师兄,微信:zhuan2quan"
  26.                 .contact(new Contact("二师兄""https://www.choupangxia.com/""secbro2@gmail.com")) 
  27.                 .version("1.0"
  28.                 .build(); 
  29.     } 
  30.  
  31.     /** 
  32.      * 封装全局通用参数 
  33.      */ 
  34.     private List<RequestParameter> getGlobalRequestParameters() { 
  35.         List<RequestParameter> parameters = new ArrayList<>(); 
  36.         parameters.add(new RequestParameterBuilder() 
  37.                 .name("uuid"
  38.                 .description("设备uuid"
  39.                 .required(true
  40.                 .in(ParameterType.QUERY) 
  41.                 .query(q -> q.model(m -> m.scalarModel(ScalarType.STRING))) 
  42.                 .required(false
  43.                 .build()); 
  44.         return parameters; 
  45.     } 
  46.  
  47.     /** 
  48.      * 封装通用响应信息 
  49.      */ 
  50.     private List<Response> getGlobalResponseMessage() { 
  51.         List<Response> responseList = new ArrayList<>(); 
  52.         responseList.add(new ResponseBuilder().code("404").description("未找到资源").build()); 
  53.         return responseList; 
  54.     } 

通过以上配置已经完成了Spring Boot与Swagger的集成,下面展示一下如何在业务逻辑中进行使用。

业务中使用

创建两个实体类Goods(商品类)和CommonResult(通用返回结果类)。

Goods类:

  1. @ApiModel("商品模型"
  2. public class Goods { 
  3.  
  4.     /** 
  5.      * 商品id 
  6.      */ 
  7.     @ApiModelProperty("商品ID"
  8.     Long goodsId; 
  9.  
  10.     /** 
  11.      * 商品名称 
  12.      */ 
  13.     @ApiModelProperty("商品名称"
  14.     private String goodsName; 
  15.  
  16.     /** 
  17.      * 商品价格 
  18.      */ 
  19.     @ApiModelProperty("商品价格"
  20.     private BigDecimal price; 
  21.  
  22.     // 省略getter/setter 

CommonResult类:

  1. @ApiModel("API通用数据"
  2. public class CommonResult<T> { 
  3.  
  4.     /** 
  5.      * 标识代码,0表示成功,非0表示出错 
  6.      */ 
  7.     @ApiModelProperty("标识代码,0表示成功,非0表示出错"
  8.     private Integer code; 
  9.  
  10.     /** 
  11.      * 描述信息,通常错时使用 
  12.      */ 
  13.     @ApiModelProperty("错误描述"
  14.     private String msg; 
  15.  
  16.     /** 
  17.      * 业务数据 
  18.      */ 
  19.     @ApiModelProperty("业务数据"
  20.     private T data; 
  21.  
  22.     public CommonResult(Integer status, String msg, T data) { 
  23.         this.code = status; 
  24.         this.msg = msg; 
  25.         this.data = data; 
  26.     } 
  27.  
  28.     /** 
  29.      * 成功 
  30.      */ 
  31.     public static <T> CommonResult<T> success(T data) { 
  32.         return new CommonResult<>(0, "成功", data); 
  33.     } 
  34.  
  35.     public static <T> CommonResult<T> success(Integer code, String msg) { 
  36.         return new CommonResult<>(code, msg, null); 
  37.     } 
  38.  
  39.     /** 
  40.      * 错误 
  41.      */ 
  42.     public static <T> CommonResult<T> error(int code, String msg) { 
  43.         return new CommonResult<>(code, msg, null); 
  44.     } 
  45.  
  46.     // 省略getter/setter 

下面针对Controller层的接口来使用Swagger对应的API。

GoodsController类:

  1. @Api(tags = "商品信息管理接口"
  2. @RestController 
  3. @RequestMapping("/goods"
  4. public class GoodsController { 
  5.  
  6.     @Operation(summary = "单个商品详情"
  7.     @GetMapping("/findGoodsById"
  8.     public CommonResult<Goods> findGoodsById( 
  9.             @Parameter(description = "商品ID,正整数"
  10.             @RequestParam(value = "goodsId", required = false, defaultValue = "0"Integer goodsId) { 
  11.         System.out.println("根据商品ID=" + goodsId + "查询商品详情"); 
  12.         Goods goods = new Goods(); 
  13.         goods.setGoodsId(1L); 
  14.         goods.setGoodsName("笔记本"); 
  15.         goods.setPrice(new BigDecimal(8888)); 
  16.         return CommonResult.success(goods); 
  17.     } 

OrderController类:

  1. @Api(tags = "订单管理接口"
  2. @RestController 
  3. @RequestMapping("/order"
  4. public class OrderController { 
  5.  
  6.     @Operation(summary = "提交订单"
  7.     @PostMapping("/order"
  8.     @ApiImplicitParams({ 
  9.             @ApiImplicitParam(name = "userId", value = "用户id", dataTypeClass = Long.class, paramType = "query", example = "123"), 
  10.             @ApiImplicitParam(name = "goodsId", value = "商品id", dataTypeClass = Integer.class, paramType = "query", example = "1"
  11.     }) 
  12.     public CommonResult<String> toBuy(@ApiIgnore @RequestParam Map<String, String> params) { 
  13.         System.out.println(params); 
  14.         return CommonResult.success("success"); 
  15.     } 

展示效果

完成集成,启动SpringBoot项目,在访问地址:

http://127.0.0.1:8080/swagger-ui/index.html

从整体上可以看到如下效果:

具体的商品信息管理接口,可以看到请求参数、返回结果数据结构等信息,点击“Try it out”,可输入参数请求参数,进行接口的调用:

调用之后会返回对应的处理结果:

在最下面的Schemas中还可以看到对应返回结果数据和被Swagger注解的实体类信息。

Swagger3注解使用说明

经过上述实例之后,我们知道大多数API是如何使用的了,这了再汇总一下相关API的功能:

  1. @Api:用在请求的类上,表示对类的说明 
  2.     tags="说明该类的作用,可以在UI界面上看到的注解" 
  3.     value="该参数没什么意义,在UI界面上也看到,所以不需要配置" 
  4.  
  5. @ApiOperation:用在请求的方法上,说明方法的用途、作用 
  6.     value="说明方法的用途、作用" 
  7.     notes="方法的备注说明" 
  8.  
  9. @ApiImplicitParams:用在请求的方法上,表示一组参数说明 
  10.     @ApiImplicitParam:用在@ApiImplicitParams注解中,指定一个请求参数的各个方面 
  11.         name:参数名 
  12.         value:参数的汉字说明、解释 
  13.         required:参数是否必须传 
  14.         paramType:参数放在哪个地方 
  15.             · header --> 请求参数的获取:@RequestHeader 
  16.             · query --> 请求参数的获取:@RequestParam 
  17.             · path(用于restful接口)--> 请求参数的获取:@PathVariable 
  18.             · body(不常用) 
  19.             · form(不常用)     
  20.         dataType:参数类型,默认String,其它值dataType="Integer"        
  21.         defaultValue:参数的默认值 
  22.  
  23. @ApiResponses:用在请求的方法上,表示一组响应 
  24.     @ApiResponse:用在@ApiResponses中,一般用于表达一个错误的响应信息 
  25.         code:数字,例如400 
  26.         message:信息,例如"请求参数没填好" 
  27.         response:抛出异常的类 
  28.  
  29. @ApiModel:用于响应类上,表示一个返回响应数据的信息 
  30.             (这种一般用在post创建的时候,使用@RequestBody这样的场景, 
  31.             请求参数无法使用@ApiImplicitParam注解进行描述的时候) 
  32.     @ApiModelProperty:用在属性上,描述响应类的属性 

集成knife4j导出离线文档

Swagger为我们提供了方便的在线文档支持,但某些场景下我们需要把接口文档提供给合作人员,而不是直接给一个地址。此时,我们就需要将接口文档导出为离线文档。

这里我们集成增强文档knife4j来实现离线文档的导出。

添加knife4j依赖

在pom.xml中增加knife4j的依赖:

  1. <dependency> 
  2.     <groupId>com.github.xiaoymin</groupId> 
  3.     <artifactId>knife4j-spring-boot-starter</artifactId> 
  4.     <version>3.0.2</version> 
  5. </dependency> 

 

启动knife4j

在上面配置Swagger的Swagger3Config中添加@EnableKnife4j注解,该注解可以开启knife4j的增强功能。

  1. @EnableKnife4j 
  2. @Configuration 
  3. @EnableOpenApi 
  4. public class Swagger3Config { 
  5.     // ... 

此时,如果依旧访问http://localhost:8080/swagger-ui/index.html会发现显示并没有变化。这里我们需要访问http://localhost:8088/doc.html。

整个项目源码地址:https://github.com/secbr/springboot-all/tree/master/springboot-swagger3。

展示效果

此时启动项目,访问doc.html之后,你会发现现在文档风格变得非常酷炫。展示几个效果图来看看:

其中在“离线文档”一栏中可以看到四种形式的离线文档下载:Markdown、HTML、Word、OpenAPI。

其中个人感觉HTML格式的文档更具有没敢,也更方便查看,来一张图看看效果。

小结

文档是项目中必须的,但随着开源框架的发展,对技术人员来说文档的痛点也在逐步解决。如果你还处于手写文档的阶段,真的可以尝试一下这类更友好的文档展现形式。

 

责任编辑:武晓燕 来源: 程序新视界
相关推荐

2022-07-21 11:04:53

Swagger3Spring

2022-02-16 08:21:11

JavaSwagger工具

2021-04-13 07:29:13

Swagger3接口Postman

2021-01-18 06:19:31

SpringbooSwagger2配置

2011-08-11 13:46:04

Xcode离线安装

2017-06-20 15:39:58

Koa2 应用动态Swagger文档

2023-03-08 08:48:50

Swag工具

2017-07-20 17:05:04

JavaScriptswagger-decSwagger

2023-03-06 08:53:13

2023-08-09 08:37:44

2023-09-21 10:44:41

Web服务Swagger前端

2011-07-26 17:39:53

Xcode iPhone 文档

2020-12-07 06:05:34

apidocyapiknife4j

2021-05-26 06:22:34

SpringBootJPA后端开发

2021-06-05 07:34:00

SpringBootMybatis用法

2021-07-11 07:05:28

RedisSpringBoot用法

2023-01-11 15:11:36

SpringEhcache

2009-07-03 11:27:11

JSP编程思想

2020-03-06 11:00:00

戴尔

2021-06-09 08:30:52

CSS33D旋转视图3D动画
点赞
收藏

51CTO技术栈公众号