Spring Boot 2.x基础教程:Swagger接口分类与各元素排序问题详解
之前通过Spring Boot 2.x基础教程:使用Swagger2构建强大的API文档一文,我们学习了如何使用Swagger为Spring Boot项目自动生成API文档,有不少用户留言问了关于文档内容的组织以及排序问题。所以,就特别开一篇详细说说Swagger中文档内容如何来组织以及其中各个元素如何控制前后顺序的具体配置方法。
接口的分组
我们在Spring Boot中定义各个接口是以Controller
作为第一级维度来进行组织的,Controller
与具体接口之间的关系是一对多的关系。我们可以将同属一个模块的接口定义在一个Controller
里。默认情况下,Swagger是以Controller
为单位,对接口进行分组管理的。这个分组的元素在Swagger中称为Tag
,但是这里的Tag
与接口的关系并不是一对多的,它支持更丰富的多对多关系。
默认分组
首先,我们通过一个简单的例子,来看一下默认情况,Swagger是如何根据Controller来组织Tag与接口关系的。定义两个Controller
,分别负责教师管理与学生管理接口,比如下面这样:
@RestController
@RequestMapping(value = "/teacher")
static class TeacherController {
@GetMapping("/xxx")
public String xxx() {
return "xxx";
}
}
@RestController
@RequestMapping(value = "/student")
static class StudentController {
@ApiOperation("获取学生清单")
@GetMapping("/list")
public String bbb() {
return "bbb";
}
@ApiOperation("获取教某个学生的老师清单")
@GetMapping("/his-teachers")
public String ccc() {
return "ccc";
}
@ApiOperation("创建一个学生")
@PostMapping("/aaa")
public String aaa() {
return "aaa";
}
}
启动应用之后,我们可以看到Swagger中这两个Controller是这样组织的:
图中标出了Swagger默认生成的Tag
与Spring Boot中Controller
展示的内容与位置。
自定义默认分组的名称
接着,我们可以再试一下,通过@Api
注解来自定义Tag
,比如这样:
@Api(tags = "教师管理")
@RestController
@RequestMapping(value = "/teacher")
static class TeacherController {
// ...
}
@Api(tags = "学生管理")
@RestController
@RequestMapping(value = "/student")
static class StudentController {
// ...
}
再次启动应用之后,我们就看到了如下的分组内容,代码中@Api
定义的tags
内容替代了默认产生的teacher-controller
和student-controller
。
合并Controller分组
到这里,我们还都只是使用了Tag
与Controller
一一对应的情况,Swagger中还支持更灵活的分组!从@Api
注解的属性中,相信聪明的读者一定已经发现tags
属性其实是个数组类型:
我们可以通过定义同名的Tag
来汇总Controller
中的接口,比如我们可以定义一个Tag
为“教学管理”,让这个分组同时包含教师管理和学生管理的所有接口,可以这样来实现:
@Api(tags = {"教师管理", "教学管理"})
@RestController
@RequestMapping(value = "/teacher")
static class TeacherController {
// ...
}
@Api(tags = {"学生管理", "教学管理"})
@RestController
@RequestMapping(value = "/student")
static class StudentController {
// ...
}
最终效果如下:
更细粒度的接口分组
通过@Api
可以实现将Controller
中的接口合并到一个Tag
中,但是如果我们希望精确到某个接口的合并呢?比如这样的需求:“教学管理”包含“教师管理”中所有接口以及“学生管理”管理中的“获取学生清单”接口(不是全部接口)。
那么上面的实现方式就无法满足了。这时候发,我们可以通过使用@ApiOperation
注解中的tags
属性做更细粒度的接口分类定义,比如上面的需求就可以这样子写:
@Api(tags = {"教师管理","教学管理"})
@RestController
@RequestMapping(value = "/teacher")
static class TeacherController {
@ApiOperation(value = "xxx")
@GetMapping("/xxx")
public String xxx() {
return "xxx";
}
}
@Api(tags = {"学生管理"})
@RestController
@RequestMapping(value = "/student")
static class StudentController {
@ApiOperation(value = "获取学生清单", tags = "教学管理")
@GetMapping("/list")
public String bbb() {
return "bbb";
}
@ApiOperation("获取教某个学生的老师清单")
@GetMapping("/his-teachers")
public String ccc() {
return "ccc";
}
@ApiOperation("创建一个学生")
@PostMapping("/aaa")
public String aaa() {
return "aaa";
}
}
效果如下图所示:
内容的顺序
在完成了接口分组之后,对于接口内容的展现顺序又是众多用户特别关注的点,其中主要涉及三个方面:分组的排序、接口的排序以及参数的排序,下面我们就来逐个说说如何配置与使用。
分组的排序
关于分组排序,也就是Tag的排序。目前版本的Swagger支持并不太好,通过文档我们可以找到关于Tag排序的配置方法。
第一种:原生Swagger用户,可以通过如下方式:
第二种:Swagger Starter用户,可以通过修改配置的方式:
swagger.ui-config.tags-sorter=alpha
似乎找到了希望,但是其实这块并没有什么可选项,一看源码便知:
public enum TagsSorter {
ALPHA("alpha");
private final String value;
TagsSorter(String value) {
this.value = value;
}
@JsonValue
public String getValue() {
return value;
}
public static TagsSorter of(String name) {
for (TagsSorter tagsSorter : TagsSorter.values()) {
if (tagsSorter.value.equals(name)) {
return tagsSorter;
}
}
return null;
}
}
是的,Swagger只提供了一个选项,就是按字母顺序排列。那么我们要如何实现排序呢?这里笔者给一个不需要扩展源码,仅依靠使用方式的定义来实现排序的建议:为Tag的命名做编号。比如:
@Api(tags = {"1-教师管理","3-教学管理"})
@RestController
@RequestMapping(value = "/teacher")
static class TeacherController {
// ...
}
@Api(tags = {"2-学生管理"})
@RestController
@RequestMapping(value = "/student")
static class StudentController {
@ApiOperation(value = "获取学生清单", tags = "3-教学管理")
@GetMapping("/list")
public String bbb() {
return "bbb";
}
// ...
}
由于原本存在按字母排序的机制在,通过命名中增加数字来帮助排序,可以简单而粗暴的解决分组问题,最后效果如下:
接口的排序
在完成了分组排序问题(虽然不太优雅...)之后,在来看看同一分组内各个接口该如何实现排序。同样的,凡事先查文档,可以看到Swagger也提供了相应的配置,下面也分两种配置方式介绍:
第一种:原生Swagger用户,可以通过如下方式:
第二种:Swagger Starter用户,可以通过修改配置的方式:
swagger.ui-config.operations-sorter=alpha
很庆幸,这个配置不像Tag的排序配置没有可选项。它提供了两个配置项:alpha
和method
,分别代表了按字母表排序以及按方法定义顺序排序。当我们不配置的时候,改配置默认为alpha
。两种配置的效果对比如下图所示:
参数的排序
完成了接口的排序之后,更细粒度的就是请求参数的排序了。默认情况下,Swagger对Model参数内容的展现也是按字母顺序排列的。所以之前教程中的User对象在文章中展现如下:
如果我们希望可以按照Model中定义的成员变量顺序来展现,那么需要我们通过@ApiModelProperty
注解的position
参数来实现位置的设置,比如:
@Data
@ApiModel(description = "用户实体")
public class User {
@ApiModelProperty(value = "用户编号", position = 1)
private Long id;
@NotNull
@Size(min = 2, max = 5)
@ApiModelProperty(value = "用户姓名", position = 2)
private String name;
@NotNull
@Max(100)
@Min(10)
@ApiModelProperty(value = "用户年龄", position = 3)
private Integer age;
@NotNull
@Email
@ApiModelProperty(value = "用户邮箱", position = 4)
private String email;
}
最终效果如下:
小结
本文详细的介绍了Swagger中对接口内容的组织控制。有些问题并没有通过配置来解决,也可能是对文档或源码内容的了解不够深入。如果读者有更好的实现方案,欢迎提出与交流。
代码示例
本文的完整工程可以查看下面仓库中的chapter2-4
目录:
- Github:https://github.com/dyc87112/SpringBoot-Learning/tree/2.x
- Gitee:https://gitee.com/didispace/SpringBoot-Learning/tree/2.x
如果您觉得本文不错,欢迎Star支持,您的关注是我坚持的动力!
相关资料
- https://swagger.io/docs/
- http://blog.didispace.com/spring-boot-learning-21-2-2/
- https://github.com/SpringForAll/spring-boot-starter-swagger
欢迎关注我的公众号:程序猿DD,获得独家整理的学习资源和日常干货推送。
如果您对我的专题内容感兴趣,也可以关注我的博客:didispace.com
Spring Boot 2.x基础教程:Swagger接口分类与各元素排序问题详解的更多相关文章
- Spring Boot 2.x基础教程:Swagger静态文档的生成
前言 通过之前的两篇关于Swagger入门以及具体使用细节的介绍之后,我们已经能够轻松地为Spring MVC的Web项目自动构建出API文档了.如果您还不熟悉这块,可以先阅读: Spring Boo ...
- Spring Boot 2.x基础教程:使用Swagger2构建强大的API文档
随着前后端分离架构和微服务架构的流行,我们使用Spring Boot来构建RESTful API项目的场景越来越多.通常我们的一个RESTful API就有可能要服务于多个不同的开发人员或开发团队:I ...
- Spring Boot 2.x基础教程:JSR-303实现请求参数校验
请求参数的校验是很多新手开发非常容易犯错,或存在较多改进点的常见场景.比较常见的问题主要表现在以下几个方面: 仅依靠前端框架解决参数校验,缺失服务端的校验.这种情况常见于需要同时开发前后端的时候,虽然 ...
- Spring Boot 2.x基础教程:使用国产数据库连接池Druid
上一节,我们介绍了Spring Boot在JDBC模块中自动化配置使用的默认数据源HikariCP.接下来这一节,我们将介绍另外一个被广泛应用的开源数据源:Druid. Druid是由阿里巴巴数据库事 ...
- Spring Boot 2.x基础教程:找回启动日志中的请求路径列表
如果您看过之前的Spring Boot 1.x教程,或者自己原本就对Spring Boot有一些经验,或者对Spring MVC很熟悉.那么对于Spring构建的Web应用在启动的时候,都会输出当前应 ...
- Spring Boot 2.x基础教程:事务管理入门
什么是事务? 我们在开发企业应用时,通常业务人员的一个操作实际上是对数据库读写的多步操作的结合.由于数据操作在顺序执行的过程中,任何一步操作都有可能发生异常,异常会导致后续操作无法完成,此时由于业务逻 ...
- Spring Boot 2.x基础教程:进程内缓存的使用与Cache注解详解
随着时间的积累,应用的使用用户不断增加,数据规模也越来越大,往往数据库查询操作会成为影响用户使用体验的瓶颈,此时使用缓存往往是解决这一问题非常好的手段之一.Spring 3开始提供了强大的基于注解的缓 ...
- Spring Boot 2.x基础教程:使用EhCache缓存集群
上一篇我们介绍了在Spring Boot中整合EhCache的方法.既然用了ehcache,我们自然要说说它的一些高级功能,不然我们用默认的ConcurrentHashMap就好了.本篇不具体介绍Eh ...
- Spring Boot 2.x基础教程:如何扩展XML格式的请求和响应
在之前的所有Spring Boot教程中,我们都只提到和用到了针对HTML和JSON格式的请求与响应处理.那么对于XML格式的请求要如何快速的在Controller中包装成对象,以及如何以XML的格式 ...
随机推荐
- 牛客练习赛17 B-好位置
传送门 题意:本来惯例中文题不解释的, 但是有些人不懂这个题意, 简单的来说, 就是s1每一个的每一个字符都可以和别的字符构成一个子串 == s2. 算了还是惯例中文题意不解释吧. 题解:其实以前写 ...
- 模板汇总——快读 fread
struct FastIO { ; int wpos; char wbuf[S]; FastIO() : wpos() { } inline int xchar() { static char buf ...
- 【Offer】[66] 【构建乘积数组】
题目描述 思路分析 测试用例 Java代码 代码链接 题目描述 给定一个数组A[0, 1, -, n-1],请构建一个数组B[0, 1, -, n-1],其中B中的元素B[i] =A[0]×A[1]× ...
- Marrkdown基础用法
目录 前言 markdown简介 用法列表 标题 字符效果和横线 引用 锚点与链接 代码高亮 图片 有序列表&无序列表 表格 特殊符号与颜色处理 markdown进阶技巧 参考文章 前言 因为 ...
- 题解 洛谷P2833 【等式】
运用暴力解方程吸氧过了这道题 通过数据范围看,要是枚举x和y只能炸掉三成的数据. 所以考虑枚举从x1到x2枚举x,通过方程移项可知y=-(ax+c)/b,再判断y是否在y1和y2之间即可. 本题本做法 ...
- Nginx 反向代理基本框架
全局配置指令:user nginx; 模块配置段 # 事件驱动模块,提供并发响应功能events{......}# http模块,提供web请求处理,可嵌套其他重要模块http{.......#ser ...
- 关于格林尼治时间(GMT)和DateTime相互转换的分享
普及一下什么是格林尼治时间? 世界时UT即格林尼治 平太阳时间,是指格林尼治所在地的标准时间,也是表示地球自转速率的一种形式.以地球自转为基础的时间计量系统.地球自转的角度可用地方子午线相对于地球上的 ...
- FreeSql (二十二)Dto 映射查询
适合喜欢使用 dto 的朋友,很多时候 entity 与 dto 属性名相同,属性数据又不完全一致. 有的人先查回所有字段数据,再使用 AutoMapper 映射. 我们的功能是先映射,再只查询映射好 ...
- apk签名发布及其原理
如果我们在ADT中开发完了一个android项目,如何将它打包呢?方法如下: 1.unsigned APP(无签名的APP) 最懒惰的方法,可以直接在项目的bin目录下直接将apk拷贝出来,就ok了. ...
- Azure虚拟机时间同步问题
场景描述:在Azure上新创建虚拟机默认是UTC时区的,因为业务在国内,所以要修改在CST注:协调世界时(英语:Coordinated Universal Time,法语:Temps Universe ...