Swagger-文档框架学习使用笔记

Swagger-文档框架学习使用笔记

对于接口开发,常常与编写文档多多少少脱不了干系。

这时就想有没有什么相关的工具可以使用呢?

What

Swagger 是一个规范且完整的框架,用于生成、描述、调用和可视化 RESTful 风格的 Web 服务。

Swagger 的目标是对 REST API 定义一个标准且和语言无关的接口,可以让人和计算机拥有无须访问源码、文档或网络流量监测就可以发现和理解服务的能力。当通过 Swagger 进行正确定义,用户可以理解远程服务并使用最少实现逻辑与远程服务进行交互。与为底层编程所实现的接口类似,Swagger 消除了调用服务时可能会有的猜测。

简而言之,就是对接项目接口生成API文档、调试功能。

同行对比

以我所接触过的Yapi做对比,Swagger是与项目或模块耦合的,项目运行时才会有Swagger的页面。

How

Version 2.9.2

SpringBoot

  1. 引入依赖

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    <!--Swagger开发-->
    <dependency>
    <groupId>io.springfox</groupId>
    <artifactId>springfox-swagger2</artifactId>
    <version>${swagger.version}</version>
    </dependency>
    <!--Swagger页面-->
    <dependency>
    <groupId>io.springfox</groupId>
    <artifactId>springfox-swagger-ui</artifactId>
    <version>${swagger.version}</version>
    </dependency>
  2. 配置Swagger

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    @Bean
    public Docket webApiConfig(){
    return new Docket(DocumentationType.SWAGGER_2)
    .groupName("Web-Api")
    .apiInfo(webApiInfo())
    .select()
    .paths(PathSelectors.regex("/api/.*"))
    //.apis(RequestHandlerSelectors.basePackage("com.aaaxxx.controller"))
    .build();
    }
    private ApiInfo webApiInfo() {
    return new ApiInfoBuilder()
    .title("网站Api文档")
    .description("本文档描述网站微服务接口定义")
    .version("1.0")
    .contact(new Contact("minmin", "https://github.com/aaaxxx", "[email protected]"))
    .build();
    }

    可以通过以下两种方式发布相关API

    • apis

      配置接口(控制器)所在的包进行发布

    • paths

      配置访问路径进行发布

  3. 编写Swagger代码

    对所涉及的相关API进行两个层面的编写

    • Controller
    • Model
Swagger的注解
Controller
  • @Api
  • @ApiOperation
  • @ApiImplicitParams
  • @ApiImplicitParam
  • @ApiParam
Model
  • @ApiModel
  • @ApiModelProperty
Swagger的使用案例
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
100
101
102
103
/**
* The type Hospital set controller.
*
* @author minmin
* @date 2021 /08/08 18:24
* @since 1.0
*/
@Api("医院设置管理")
@Slf4j
@RestController
@RequestMapping("/admin/hosp/hospitalSet")
public class HospitalSetController {

private static final String LOG_PARAMS_STR = "params is:{}";

@Resource
private IHospitalSetService hospitalSetService;

@ApiOperation("查询全部医院信息")
@GetMapping
public Result<List<HospitalSet>> findAll() {
List<HospitalSet> hospitalSets = hospitalSetService.list();
log.info("query size:{}", hospitalSets.size());
return new Result.Builder<List<HospitalSet>>().success(hospitalSets).build();
}

@ApiOperation("批量条件查询医院信息")
@ApiImplicitParams({
@ApiImplicitParam(paramType = "path", name = "currPage", value = "第几页", required = true, dataType = "String"),
@ApiImplicitParam(paramType = "path", name = "pageSize", value = "每页数量", required = true, dataType = "String"),
@ApiImplicitParam(paramType = "body", name = "hospitalQueryVo", value = "医院参数", dataType = "HospitalQueryVo"),
})
@PostMapping("/{currPage}/{pageSize}")
public Result<Page<HospitalSet>> findByPage(
@PathVariable Integer currPage,
@PathVariable Integer pageSize,
@RequestBody(required = false) HospitalQueryVo hospitalQueryVo) {
log.info("query params currPage:{}, pageSize:{}", currPage, pageSize);
Page<HospitalSet> page = new Page<>(currPage, pageSize);
QueryWrapper<HospitalSet> queryWrapper = new QueryWrapper<>();
if (hospitalQueryVo != null) {
log.info("body params is:{}", hospitalQueryVo);
if (!StringUtils.isEmpty(hospitalQueryVo.getHoscode())) {
queryWrapper.eq("hoscode", hospitalQueryVo.getHoscode());
}
if (!StringUtils.isEmpty(hospitalQueryVo.getHosname())) {
queryWrapper.like("hosname", hospitalQueryVo.getHosname());
}
}
Page<HospitalSet> hospitalSetPage = hospitalSetService.page(page, queryWrapper);
return new Result.Builder<Page<HospitalSet>>().success(hospitalSetPage).build();
}

@ApiOperation("根据id查询医院")
@ApiImplicitParam(paramType = "path", name = "id", value = "医院id", required = true, dataType = "String")
@GetMapping("/{id}")
public Result<HospitalSet> findById(@PathVariable Integer id) {
log.info(LOG_PARAMS_STR, id);
HospitalSet hospitalSet = hospitalSetService.getById(id);
return new Result.Builder<HospitalSet>().success(hospitalSet).build();
}

@ApiOperation("保存或更新医院")
@ApiImplicitParam(paramType = "body", name = "hospitalSet", value = "医院Json字符串", required = true, dataType = "HospitalSet")
@PutMapping
public Result<String> updateById(@RequestBody HospitalSet hospitalSet) {
if (checkRequestAndId(hospitalSet)) {
return Result.fastFail();
}
log.info(LOG_PARAMS_STR, hospitalSet);
generateUsableKeys(hospitalSet);
return hospitalSetService.saveOrUpdate(hospitalSet) ? Result.fastSuccess() : Result.fastFail();
}

@ApiOperation("根据id删除医院")
@ApiImplicitParam(paramType = "path", name = "id", value = "医院id", required = true, dataType = "String")
@DeleteMapping("/{id}")
public Result<String> deleteById(@PathVariable Integer id) {
log.info(LOG_PARAMS_STR, id);
return hospitalSetService.removeById(id) ? Result.fastSuccess() : Result.fastFail();
}

@ApiOperation("批量删除医院")
@DeleteMapping
public Result<String> batchDeleteByIds(
@RequestBody @ApiParam(name = "ids", value = "id的Json数组", required = true)
List<Integer> ids) {
if (ids.isEmpty()) {
return Result.fastFail();
}
log.info(LOG_PARAMS_STR, ids);
return hospitalSetService.removeByIds(ids) ? Result.fastSuccess() : Result.fastFail();
}

private void generateUsableKeys(HospitalSet hospitalSet) {
hospitalSet.setStatus(1);
hospitalSet.setSignKey(UUID.randomUUID().toString().replace("-", ""));
}

private boolean checkRequestAndId(HospitalSet hospitalSet) {
return hospitalSet == null || hospitalSet.getId() == null;
}
}
Model
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
/**
* The type Hospital set.
*
* @author minmin
* @since 1.0
*/
@Getter
@Setter
@ToString
@EqualsAndHashCode(callSuper = false)
@ApiModel(value = "HospitalSet", description = "医院设置")
@TableName("hospital_set")
public class HospitalSet extends BaseEntity {

private static final long serialVersionUID = 1L;

@ApiModelProperty(value = "医院名称")
@TableField("hosname")
private String hosname;

@ApiModelProperty(value = "医院编号")
@TableField("hoscode")
private String hoscode;

@ApiModelProperty(value = "api基础路径")
@TableField("api_url")
private String apiUrl;

@ApiModelProperty(value = "签名秘钥")
@TableField("sign_key")
private String signKey;

@ApiModelProperty(value = "联系人姓名")
@TableField("contacts_name")
private String contactsName;

@ApiModelProperty(value = "联系人手机")
@TableField("contacts_phone")
private String contactsPhone;

@ApiModelProperty(value = "状态")
@TableField("status")
private Integer status;

}
踩坑
@ApiImplicitParam

该注解有几个属性值得注意

  • paramType

    该属性有三个参数

    • path:标识参数在url中占位
    • query:标识参数为GET中的query params
    • body:标识参数在请求体中
  • name

    该属性视paramType的值而定,为了万金油,直接与方法参数名保持一致即可。

    @ApiModel的value属性与之关联,直接使用类名就能保证万金油

  • value

    这个属性才是你可以随意编写的,表名参数的含义

  • dataType

    这个属性只有两个值,string与int(可以大骆驼峰)

我不知道它为什么不在一些属性中限定一个枚举类

@ApiParam

该注解打在方法的参数前,用于标记Java的集合类,具体看使用案例


文章可能还会不定期更新,如其他Swaager版本的使用或与其他框架的整合


Swagger-文档框架学习使用笔记
https://blog.gugu.dev/2024-02-21/Swagger-文档框架学习使用笔记/
作者
MinMin
发布于
2024年2月21日
许可协议