SpringBoot整合Swagger2

如何构建一份合理高效的接口文档很重要,Swagger的出现可以完美解决了传统接口管理方式存在的痛点。以下介绍Spring Boot整合Swagger2的流程,连带填坑。

SpringBoot整合Swagger2

  • 引入相应的maven包

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    <dependency>
    <groupId>io.springfox</groupId>
    <artifactId>springfox-swagger2</artifactId>
    <version>2.7.0</version>
    </dependency>

    <dependency>
    <groupId>io.springfox</groupId>
    <artifactId>springfox-swagger-ui</artifactId>
    <version>2.7.0</version>
    </dependency>
  • 编写Swagger2的配置类

    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
    package com.swagger.demo.config;

    import io.swagger.annotations.Api;
    import org.springframework.beans.factory.annotation.Value;
    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.Configuration;
    import springfox.documentation.builders.ApiInfoBuilder;
    import springfox.documentation.builders.PathSelectors;
    import springfox.documentation.builders.RequestHandlerSelectors;
    import springfox.documentation.service.ApiInfo;
    import springfox.documentation.spi.DocumentationType;
    import springfox.documentation.spring.web.plugins.Docket;
    import springfox.documentation.swagger2.annotations.EnableSwagger2;

    /**
    * @author Mr.zhang
    * @description swagger配置类
    * @date 9:06 AM 2019/4/17
    */
    @Configuration
    @EnableSwagger2
    public class Swagger2Config {
    @Value("${swagger2.enable}")
    private boolean enable;

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

    private ApiInfo apiInfo() {
    return new ApiInfoBuilder()
    .title("Demo模块接口文档")
    .description("提供Demo模块文档")
    .termsOfServiceUrl("https://xingtian.github.io/trace.github.io/")
    .version("1.0")
    .build();
    }
    }

    ​ 注解@EnableSwagger2开启swagger2,apiInfo是接口文档的基本说明信息,包括标题、描述、服务网址、联系人、版本等信息。

    ​ Docket创建,通过groupName进行分组,paths属性进行过滤,apis属性可以设置扫描包,或者通过注解的方式标识。

    ​ enable属性主要用于控制是否生成接口文档,比如:生产环境不生成接口文档。

  • Controller层类和方法添加相关注解

    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
    92
    93
    94
    95
    96
    97
    98
    99
    package com.swagger.demo.web;

    import com.swagger.demo.entity.ResultModel;
    import com.swagger.demo.entity.User;
    import io.swagger.annotations.Api;
    import io.swagger.annotations.ApiImplicitParam;
    import io.swagger.annotations.ApiImplicitParams;
    import io.swagger.annotations.ApiOperation;
    import org.springframework.web.bind.annotation.*;

    import java.util.ArrayList;
    import java.util.List;

    /**
    * @author Mr.zhang
    * @description Demo控制层
    * @date 9:57 AM 2019/4/17
    */
    @RestController
    @RequestMapping("/demo")
    @Api(tags = "demo模块")
    public class DemoController {


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


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


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


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


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


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


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


    @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) {
    return ResultModel.success(new User());
    }


    @DeleteMapping("/delete")
    @ApiOperation("删除单个用户")
    @ApiImplicitParam(value = "用户ID", required = true)
    public ResultModel<Integer> delete(int id) {
    return ResultModel.success(id);
    }
    }
  • 返回对象ResultModel

    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
    package com.swagger.demo.entity;

    import io.swagger.annotations.ApiModel;
    import io.swagger.annotations.ApiModelProperty;
    import lombok.Data;

    /**
    * @author Mr.zhang
    * @description 返回对象
    * @date 10:00 AM 2019/4/17
    */
    @ApiModel(description = "返回结果")
    @Data
    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);
    }
    }
  • 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
    package com.swagger.demo.entity;

    import io.swagger.annotations.ApiModel;
    import io.swagger.annotations.ApiModelProperty;
    import lombok.AllArgsConstructor;
    import lombok.Data;
    import lombok.NoArgsConstructor;

    import java.time.LocalDate;
    import java.time.LocalDateTime;

    /**
    * @author Mr.zhang
    * @description 用户表实体
    * @date 10:03 AM 2019/4/17
    */
    @Data
    @NoArgsConstructor
    @AllArgsConstructor
    @ApiModel
    public class User {
    @ApiModelProperty("用户ID") private Integer id;
    @ApiModelProperty("账户名") private String userName;
    @ApiModelProperty("用户昵称") private String nickName;
    @ApiModelProperty("真实姓名") private String realName;
    @ApiModelProperty("身份证号码") private String identityCard;
    @ApiModelProperty("性别") private String gender;
    @ApiModelProperty("出生日期") private LocalDate birth;
    @ApiModelProperty("手机号码") private String phone;
    @ApiModelProperty("邮箱") private String email;
    @ApiModelProperty("密码") private String password;
    @ApiModelProperty("用户头像地址") private String logo;
    @ApiModelProperty("账户状态 0:正常; 1:冻结; 2:注销") private Byte status;
    @ApiModelProperty("个性签名") private String summary;
    @ApiModelProperty("用户所在区域码") private String areaCode;
    @ApiModelProperty("注册时间") private LocalDateTime registerTime;
    @ApiModelProperty("最近登录时间") private LocalDateTime lastLoginTime;
    }

    Swagger2几个重要注解

    @Api:用在请求的类上,表示对类的说明

    • tags “说明该类的作用,可以在UI界面上看到的注解”

    • value “该参数没什么意义,在UI界面上也看到,所以不需要配置”

    @ApiOperation:用在请求的方法上,说明方法的用途、作用

    • value=”说明方法的用途、作用”
    • notes=”方法的备注说明”

    @ApiImplicitParams:用在请求的方法上,表示一组参数说明 @ApiImplicitParam:用在@ApiImplicitParams注解中,指定一个请求参数的各个方面

    • value:参数的汉字说明、解释

    • required:参数是否必须传

    • paramType: 参数放在哪个地方

      • 1.header –> 请求参数的获取:@RequestHeader
      • 2.query –> 请求参数的获取:@RequestParam
      • 3.path(用于restful接口)–> 请求参数的获取:@PathVariable
      • 4.body(不常用)
      • 5.form(不常用)
    • dataType:参数类型,默认String,其它值dataType=”Integer”

    • defaultValue:参数的默认值

    @ApiResponses:用在请求的方法上,表示一组响应 @ApiResponse:用在@ApiResponses中,一般用于表达一个错误的响应信息

    • code:数字,例如400
    • message:信息,例如”请求参数没填好”
    • response:抛出异常的类

    @ApiModel:主要有两种用途:

    • 用于响应类上,表示一个返回响应数据的信息

    • 入参实体:使用@RequestBody这样的场景, 请求参数无法使用@ApiImplicitParam注解进行描述的时候

    @ApiModelProperty:用在属性上,描述响应类的属性 最终呈现结果

  • 启动应用后,会自动生成页面

    地址:http://{root-path}/swagger-ui.htmlhttp://localhost:8080/swagger-ui.html

    效果如下:

    利用该文档可以在线测试接口