SpringBoot整合Swagger2

1.Swagger 简介

Swagger 是一套基于 OpenAPI 规范构建的开源工具,可以帮助我们设计、构建、记录以及使用 Rest API。Swagger 主要包含了以下三个部分:

  1. Swagger Editor:基于浏览器的编辑器,我们可以使用它编写我们 OpenAPI 规范。
  2. Swagger UI:它会将我们编写的 OpenAPI 规范呈现为交互式的 API 文档,后文我将使用浏览器来查看并且操作我们的 Rest API。
  3. Swagger Codegen:它可以通过为 OpenAPI(以前称为 Swagger)规范定义的任何 API 生成服务器存根和客户端 SDK 来简化构建过程。

2.为什么要使用 Swagger

当下很多公司都采取前后端分离的开发模式,前端和后端的工作由不同的工程师完成。在这种开发模式下,维持一份及时更新且完整的 Rest API 文档将会极大的提高我们的工作效率。传统意义上的文档都是后端开发人员手动编写的,相信大家也都知道这种方式很难保证文档的及时性,这种文档久而久之也就会失去其参考意义,反而还会加大我们的沟通成本。而 Swagger 给我们提供了一个全新的维护 API 文档的方式,下面我们就来了解一下它的优点:

  1. 代码变,文档变。只需要少量的注解,Swagger 就可以根据代码自动生成 API 文档,很好的保证了文档的时效性。
  2. 跨语言性,支持 40 多种语言。
  3. Swagger UI 呈现出来的是一份可交互式的 API 文档,我们可以直接在文档页面尝试 API 的调用,省去了准备复杂的调用参数的过程。
  4. 还可以将文档规范导入相关的工具(例如 SoapUI), 这些工具将会为我们自动地创建自动化测试。

3.准备 Spring Boot Web 项目

1.创建项目

2.添加依赖

1
2
3
4
5
6
7
8
9
10
11
<!--    swagger api测试    -->
<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>

3.编写接口

  1. Controller

    注意此处的@RequestMapping("/user") user一定是已经定义的APIModel,否则接口不显示

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    @RestController @RequestMapping("/user")
    @Api(tags = "用户管理")
    public class UserController {
    @Resource private UserService userService;

    @GetMapping("/query/{id}")
    @ApiOperation("通过ID查询")
    @ApiImplicitParam(name = "id", value = "用户ID", required = true, dataType = "int", paramType = "path")
    public ResultModel<User> findById(@PathVariable int id) {
    User user = userService.findById(id);
    return ResultModel.success("id查询成功", user);
    }


    @GetMapping("/query/ids")
    @ApiOperation("通过ID列表查询")
    public ResultModel<List<User>> findByIdIn(int[] ids) {
    List<User> users = userService.findByIdIn(ids);
    return ResultModel.success("in查询成功", users);
    }


    @GetMapping("/query/user")
    @ApiOperation("通过用户实体查询")
    public ResultModel<List<User>> findByUser(User user) {
    List<User> users = userService.findByUser(user);
    return ResultModel.success("通过实体查询成功", users);
    }


    @GetMapping("/query/all")
    @ApiOperation("查询所有用户")
    public ResultModel<List<User>> findAll() {
    List<User> users = userService.findAll();
    return ResultModel.success("全体查找成功", users);
    }


    @GetMapping("/query/username")
    @ApiOperation("通过用户名称模糊查询")
    @ApiImplicitParam(name = "userName", value = "用户名称")
    public ResultModel<List<User>> findByUserName(String userName) {
    List<User> users = userService.findByUserName(userName);
    return ResultModel.success(users);
    }


    @PostMapping("/insert")
    @ApiOperation("新增默认用户")
    public ResultModel<Integer> insert() {
    User user = new User();
    user.setUserName("zhongshiwen");
    user.setNickName("zsw");
    user.setRealName("钟仕文");
    user.setPassword("zsw123456");
    user.setGender("男");
    Area area = new Area();
    area.setLevel((byte) 5);
    user.setArea(area);
    userService.save(user);
    return ResultModel.success("新增用户成功", user.getId());
    }


    @PutMapping("/update")
    @ApiOperation("更新用户信息")
    public ResultModel<Integer> update(User user) {
    int row = userService.update(user);
    return ResultModel.success(row);
    }


    @PutMapping("/update/status")
    @ApiOperation("更新单个用户状态")
    @ApiImplicitParams({
    @ApiImplicitParam(name = "id", value = "用户ID", required = true),
    @ApiImplicitParam(name = "status", value = "状态", required = true)
    })
    public ResultModel<User> updateStatus(int id, byte status) {
    User user = userService.updateStatus(id, status);
    return ResultModel.success(user);
    }


    @DeleteMapping("/delete")
    @ApiOperation("删除单个用户")
    @ApiImplicitParam(value = "用户ID", required = true)
    public ResultModel<Integer> delete(int id) {
    return ResultModel.success(userService.delete(id));
    }
    }
  1. Entity
1
2
3
4
5
6
7
8
9
10
11
12
13
14
@Data @NoArgsConstructor @AllArgsConstructor
@ApiModel
public class User {
@ApiModelProperty("用户ID") private Integer id;
@ApiModelProperty("账户名") private String userName;
@ApiModelProperty("注册时间") private LocalDateTime registerTime;
@ApiModelProperty("最近登录时间") private LocalDateTime lastLoginTime;

@NotPersistent @ApiModelProperty(hidden = true)
private transient Area area; //用户所在地区

@NotPersistent @ApiModelProperty(hidden = true)
private transient List<Role> roles; //用户角色列表
}
  1. 返回结果
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
@Getter @Setter @ApiModel(description = "返回结果")
public final class ResultModel<T> {
@ApiModelProperty("是否成功: true or false")
private boolean result;
@ApiModelProperty("描述性原因")
private String message;
@ApiModelProperty("业务数据")
private T data;

private ResultModel(boolean result, String message, T data) {
this.result = result;
this.message = message;
this.data = data;
}

public static<T> ResultModel<T> success(T data) {
return new ResultModel<>(true, "SUCCESS", data);
}


public static<T> ResultModel<T> success(String message, T data) {
return new ResultModel<>(true, message, data);
}


public static ResultModel failure() {
return new ResultModel<>(false, "FAILURE", null);
}


public static ResultModel failure(String message) {
return new ResultModel<>(false, message, null);
}
}

4.配置Swagger

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
@Configuration @EnableSwagger2
public class Swagger2Config {
@Value("${swagger2.enable}") private boolean enable;

@Bean("UserApis")
public Docket userApis() {
return new Docket(DocumentationType.SWAGGER_2)
.groupName("用户模块")
.select()
.apis(RequestHandlerSelectors.withClassAnnotation(Api.class))
.paths(PathSelectors.regex("/user.*"))
.build()
.apiInfo(apiInfo())
.enable(enable);
}

@Bean("CustomApis")
public Docket customApis() {
return new Docket(DocumentationType.SWAGGER_2)
.groupName("客户模块")
.select()
.apis(RequestHandlerSelectors.withClassAnnotation(Api.class))
.paths(PathSelectors.regex("/custom.*"))
.build()
.apiInfo(apiInfo())
.enable(enable);
}

private ApiInfo apiInfo() {
return new ApiInfoBuilder()
.title("XXXXX系统平台接口文档")
.description("提供子模块1/子模块2/子模块3的文档")
.termsOfServiceUrl("https://kid1999.github.io/")
.version("1.0")
.build();
}
}

5.验证

启动应用后,会自动生成http://{root-path}/swagger-ui.html页面,访问后,效果如下所示:

img

4.Swagger UI 的使用

接口查看

SwaggerUI 会以列表的方式展示所有扫描到的接口,初始状态是收缩的,我们只需要点击展开就好,而且会在左边标识接口的请求方式(GET、POST、PUT、DELETE 等等)。

Swagger 接口列表界面

图 5. Swagger 接口列表界面

接口调用

如下图所示,点击接口展开后页面右上角的 Try it out 按钮后,页面会变成如图所示:

接口详情界面

图 6. 接口详情界面

SwaggerUI 会给我们自动填充请求参数的数据结构,我们需要做的只是点击 Execute 即可发起调用

接口调用界面

图 7. 接口调用界面

Model

如下图所示,SwaggerUI 会通过我们在实体上使用的 @ApiModel 注解以及 @ApiModelProperty 注解来自动补充实体以及其属性的描述和备注。

图 8. 实体界面

图 8. 实体界面

5.常用的Swagger2注解

Controller 相关注解

@Api: 可设置对控制器的描述。

@Api 主要属性

注解属性 类型 描述
tags String[] 控制器标签。
description String 控制器描述(该字段被申明为过期)。

接口相关注解

@ApiOperation: 可设置对接口的描述。

@ApiOperation 主要属性

注解属性 类型 描述
value String 接口说明。
notes String 接口发布说明。
tags Stirng[] 标签。
response Class<?> 接口返回类型。
httpMethod String 接口请求方式。

@ApiIgnore: Swagger 文档不会显示拥有该注解的接口。 @ApiImplicitParams: 用于描述接口的非对象参数集。 @ApiImplicitParam: 用于描述接口的非对象参数,一般与 @ApiImplicitParams 组合使用。

@ApiImplicitParam 主要属性

注解属性 描述
paramType 查询参数类型,实际上就是参数放在那里。取值:path:以地址的形式提交数据,根据 id 查询用户的接口就是这种形式传参;query:Query string 的方式传参;header:以流的形式提交;form:以 Form 表单的形式提交。
dataType 参数的数据类型。取值:Long 和 String
name 参数名字。
value 参数意义的描述。
required 是否必填。取值:true:必填参数;false:非必填参数。

Model 相关注解

@ApiModel: 可设置接口相关实体的描述。 @ApiModelProperty: 可设置实体属性的相关描述。

@ApiModelProperty 主要属性

注解属性 类型 描述
value String 字段说明。
name String 重写字段名称。
dataType Stirng 重写字段类型。
required boolean 是否必填。
example Stirng 举例说明。
hidden boolean 是否在文档中隐藏该字段。
allowEmptyValue boolean 是否允许为空。
allowableValues String 该字段允许的值,当我们 API 的某个参数为枚举类型时,使用这个属性就可以清楚地告诉 API 使用者该参数所能允许传入的值。