本文向大家介绍Spring Boot与Swagger2的搭配使用,包括Swagger2的概念、注释以及常规的使用等。


章节目录

  1. 环境
  2. 简介
  3. 场景
  4. 使用
  5. 注释
  6. 概要/分组/鉴权
  7. 总结

01

环境


Spring Boot v2.4.1, Spring v5.3.1,IntelliJ IDEA v2019.3.5,Maven v3.5, JDK 1.8 ,  MySQL 5.6, Swagger23.0.0本文中的示例代码均可在GitHub上获取,地址是:https://github.com/lovebaylong/hessian-demo-client

02

简介

Swagger是一个在线的API文档生成工具,它有两个大版本,分别是Swagger1和Swagger2,目前基本都是使用Swagger2。我们体验也是使用Swagger2版本。它不仅能动态生成接口文档还提供了测试功能,对前后端分离的开发比较友好。后端人员也不需要为前端人员写接口文档,而且它是实时生效,避免接口与文档不同步的问题。Swagger2目前最新的版本是3.0.0.0,我们今天主要讲它与Spring Boot的整合,其他的环境请自行了解。Spring Boot应用程序可以使用swagger 1.2, 2.0 和3.0版本,当然最新的最香嘛!先上几张实际运行后的效果图,示例如下:


springboot2 有必要升级3吗 springboot2.3.5_API

springboot2 有必要升级3吗 springboot2.3.5_springboot2 有必要升级3吗_02

springboot2 有必要升级3吗 springboot2.3.5_springboot 历史版本文档_03

03

场景

建议采用前后端开发模式的团队内部使用,不建议对外,对外还是建议使用独立的在线文档或是线下文档的方式,或是单独提供api官网。另外由于Swagger需要通过注释等方式侵入到业务代码里,所以会导致你的业务代码里多出很多与业务功能不相关的注释与代码等。特别是接口功能、参数、响应等越复杂要为些标注的注释与描述就越多,最后甚至Swagger相关的代码量会超过你接口的代码量。考虑如下示例:


springboot2 有必要升级3吗 springboot2.3.5_springboot2 有必要升级3吗_04

侵入式的方式把代码弄得很混杂,影响代码的纯粹性、整洁度、可阅读性、维护性等。会分散开发、阅读、维护代码时的注意力。需要团队人员都了解与熟悉Swagger以及它的各种注释与配置等,否则看到一堆注释配置等都不明白是业务上的还是非业务上的。因此一般情况我个人还是更愿意使用独立的在线文档或线下文档,让代码保持业务上的纯粹,而不需要加上各种杂七杂八的东西。当然这个也跟团队要求、个人习惯有关,仁者见仁的东西吧!


04

使用


引入Maven依赖,因为我们直接使用Spring Boot,所以直接引入它提供的starter就可以了:

<dependency>    <groupId>io.springfoxgroupId>    <artifactId>springfox-boot-starterartifactId>    <version>3.0.0version>dependency>

该starter自动为我们引入以下依赖,全景如下:


springboot2 有必要升级3吗 springboot2.3.5_API_05

非Spring Boot时,引入依赖:


<dependency>  <groupId>io.springfoxgroupId>  <artifactId>springfox-swagger2artifactId>  <version>3.0.0version>dependency><dependency>  <groupId>io.springfoxgroupId>  <artifactId>springfox-swagger-uiartifactId>  <version>3.0.0version>dependency>

这两个依赖自动为我们引入了以下依赖,全景如下:


springboot2 有必要升级3吗 springboot2.3.5_spring_06

在3.0.x系列版本里,比较之前的版本多出了springfox-oas,这个oas(OpenAPI Specification:开放API声明)里面新提供了新的注释@EnableOpenApi,它启用开放api 3.0.3规范。而像@EnableSwagger2是启用开放api  2.0规范,@EnableSwagger是启用开放api  1.2规范。springfox-oas项目主要是输出基于Spring应用程序的JSON API文档。Swagger为我们提供了几个UI访问路径,分别是:

注意:示例中的“http://localhost:8080/democlient”部分要更换你运行时的真实路径。1、所有swagger资源(组):http://localhost:8080/democlient/swagger-resources这个路径返回一个json的说明内容,描述当前的一些概要信息。如下:

springboot2 有必要升级3吗 springboot2.3.5_API_07

2、swagger的UI节点:http://localhost:8080/democlient/swagger-ui/index.html这个路径返回的就是上面的示例的效果图。或者访问:http://localhost:8080/democlient/swagger-ui/也是一样的效果,会自动forward到上面的路径。3、接口的JSON格式文档http://localhost:8080/democlient/v2/api-docs如果有分组,则路径后面还会带上当前选中分组的名称,如:http://localhost:8080/democlient/v2/api-docs?group=user-open-api如下:


springboot2 有必要升级3吗 springboot2.3.5_spring_08

swagger的UI资源都在springfox-swagger-ui-xxx.jar包里提供。


springboot2 有必要升级3吗 springboot2.3.5_API_09

在类SwaggerUiWebMvcConfigurer里进行了定义与加载,源码如下,大家可自行查阅:


springboot2 有必要升级3吗 springboot2.3.5_spring_10

如果有时候你访问UI页面时出现404,那么可以考虑一下是否版本问题,或是加载UI资源不成功,检查一下路径等。


05

注释


在Spring Boot里,我们主要通过各种注释来实现开放api的文档输出,swagger 3系列的注释由两部分组合,除了两个启动注释@EnableOpenApi和@EnableSwagger2外,其他由原来swagger-annotations-1.5.xx.jar和和swagger-annotations-2.1.x.jar提供,swagger-annotations-2.1.x.jar是由3.0版本中的oas组件包含引入的。两者提供的注释列表如下表所示:

springboot2 有必要升级3吗 springboot2.3.5_springboot 历史版本文档_11

常用注释:1、@EnableOpenApi和@EnableSwagger2在@SpringBootApplication的启动类或单独带有@Configuration的类上标注,表明该项目使用Swagger来生成开放API文档。两者用其一即可,只能标注在类、接口(包括注释@interface)或枚举上。


@Configuration//@EnableSwagger //Enable swagger 1.2 spec//@EnableSwagger2 //Enable swagger 2.0 spec@EnableOpenApi //Enable open api 3.0.3 specpublic class SwaggerConfig {......}

2、@Api用于声明当前对象是Swagger的资源,需要为该对象生成API文档,这个注释只能标注在类、接口(包括注释@interface)或枚举上。


@Api(value = "用户管理相关接口", tags = {"用户"})public class UserOpenApiController {......}

只要在类上加上该注释,则里面所有的public方法都默认会输出文档。即不在方法上增加@ApiOperation注释也一样。3、@ApiOperation表明这是一个具体的api方法或操作,为该方法生成API文档,生成测试套件等。它主要用于方法上,当然也能标注在类、接口(包括注释@interface)或枚举上,但是没啥用。


@ApiOperation(value = "根据用户编号获取用户详情,返回单个Json对象")public JsonNode detail(@RequestParam(value = "id") Long id) {  return userService.detail(id);}

4、@ApiParam主要用于接口参数说明,可标注在方法、属性、参数上。


public JsonNode detail(  @RequestParam(value = "id")   @ApiParam(value = "用户编号", required = true) Long id) {...}

效果:


springboot2 有必要升级3吗 springboot2.3.5_UI_12

5、@ApiResponses和@ApiResponse用于声明方法的响应,@ApiResponses下可包含多个@ApiResponse,@ApiResponse也可以单独使用,只声明方法的一个响应。注意这两个注释分别有两种,一种是3.0版本aos里提供,一种是原来1.5x注释jar里提供的,两者的参数值不同,但是效果都是一样的。新版本的写法:


@ApiResponses(value = {  @ApiResponse(responseCode = "401", description = "未经授权"),  @ApiResponse(responseCode = "403", description = "权限不足"),  @ApiResponse(responseCode = "404", description = "用户不存在"),  @ApiResponse(responseCode = "400", description = "用户已冻结")})

1.5版本的写法:


@ApiResponses(value = {  @ApiResponse(code = 401, message = "未经授权"),  @ApiResponse(code = 403, message = "权限不足"),  @ApiResponse(code = 404, message = "用户不存在"),  @ApiResponse(code = 400, message = "用户已冻结")})

效果如下:


springboot2 有必要升级3吗 springboot2.3.5_spring_13

6、@Authorization和@AuthorizationScope@Authorization表示该接口调用时要进行授权认证,@AuthorizationScope表示通过授权认证后的可操作范围,比如是只读,还是可读写操作等。这两个注释都只能标注在方法上。


@ApiOperation(value = "根据用户编号获取用户详情,返回单个Json对象", notes = "数据来源于Hessian接口",  authorizations = @Authorization(value = "demoClient_auth", scopes = {@AuthorizationScope(scope = "read:user", description = "用户只读")}))

如果scopes只有一个时不需要{}。增加了授权认证的接口会在UI上标识如下:


springboot2 有必要升级3吗 springboot2.3.5_springboot 历史版本文档_14

7、@ResponseHeader用于表示该接口响应的时候会有哪些特定的header,以及值类型等,可以有多个,如果只有一个时不需要{}。


@ApiOperation(value = "根据用户编号获取用户详情,返回单个Json对象", notes = "数据来源于Hessian接口",  response = ResponseEntity.class,  responseHeaders = {@ResponseHeader(name = "header1", response = String.class)},  authorizations = @Authorization(value = "token", scopes = {@AuthorizationScope(scope = "read:user", description = "用户只读")}))

效果:


springboot2 有必要升级3吗 springboot2.3.5_springboot2 有必要升级3吗_15

8、@ApiIgnore将某个方法排除掉不生成文档,因为类上加了@Api时,默认所有的public方法都会输出的。9、@ApiModel和@ApiModelProperty@ApiModel针对方法接收的参数是对象时,用该注释来声明传递的对象。能标注在类、接口(包括注释@interface)或枚举上。


@ApiModel(description = "用户信息")public class UserPojo {}

效果如下:

springboot2 有必要升级3吗 springboot2.3.5_API_16

@ApiModelProperty用于对Model的属性进行声明,一般和@ApiModel配合使用。它能标注在方法与属性上。


@ApiModelProperty(value = "用户名称", required = true)private String name;@ApiModelProperty(value = "用户年龄", required = true)private Integer age;

效果如下:


springboot2 有必要升级3吗 springboot2.3.5_springboot 历史版本文档_17

接口上只需要简单的接收该对象即可,也可以添加上例如:@ModelAttribute注释。


public JsonNode add(UserPojo user) {  ...}public JsonNode add(@ModelAttribute UserPojo user) {  ...}

06

概要/分组/鉴权

1、

概要在接口文档的UI页面上,会显示一些 默认的概要信息,如下:

springboot2 有必要升级3吗 springboot2.3.5_API_18


我们可以通过配置Docket和ApiInfo信息来定制化。定制化的效果如下:

springboot2 有必要升级3吗 springboot2.3.5_spring_19

2、分组同时由于一个系统的接口较多,我们还可以对其进行分组,

Swagger会替我们生成分组的api-docs,通过定义多个不同的Docket ,并为其指定不同的路径规则达到根据@Api标注的接口路径进行分组(分组名称只支持半角字符,中文暂时不支持,UrlEncoder.encode()了都不行)。效果如下:

springboot2 有必要升级3吗 springboot2.3.5_springboot2 有必要升级3吗_20


进行分组后,我们通过页面上进行选择,就可以查看具体分组下的接口列表了。

springboot2 有必要升级3吗 springboot2.3.5_spring_21

springboot2 有必要升级3吗 springboot2.3.5_springboot 历史版本文档_22


3、鉴权 还有接口的鉴权等,在@Authorization和@AuthorizationScope注释介绍时我们提供了示例,但是配置的内容并不会在文档上显示。这里的鉴权主要是让用户可以模拟接口要求的鉴权,比如有的接口要求在header里传递一个token类似的值,或者要求调用方OAuth2鉴权等。header的模拟比较简单,但是OAuth2鉴权的话还需要团队为此开发一个鉴权的服务才行,比较麻烦。 header鉴权效果:

springboot2 有必要升级3吗 springboot2.3.5_spring_23


随意输入一个值模拟即可:

springboot2 有必要升级3吗 springboot2.3.5_API_24


OAuth2鉴权效果:

springboot2 有必要升级3吗 springboot2.3.5_UI_25


以上的代码都可通过github获取到,该节涉及到的具体类是:https://github.com/lovebaylong/hessian-demo-client/blob/master/src/main/java/yxw/example/SwaggerConfig.java大家可自行查看与分析。

07

总结

本文针对Spring Boot + Swagger 输出在线文档,还有很多的注释与用法还有待大家去挖掘、发现与学习,大家赶紧行动起来吧!


springboot2 有必要升级3吗 springboot2.3.5_API_26