Spring Boot 2.x基础教程:Swagger接口分类与各元素排序问题详解

以前经过Spring Boot 2.x基础教程:使用Swagger2构建强大的API文档一文,咱们学习了如何使用Swagger为Spring Boot项目自动生成API文档,有很多用户留言问了关于文档内容的组织以及排序问题。因此,就特别开一篇详细说说Swagger中文档内容如何来组织以及其中各个元素如何控制先后顺序的具体配置方法。java

接口的分组

咱们在Spring Boot中定义各个接口是以Controller做为第一级维度来进行组织的,Controller与具体接口之间的关系是一对多的关系。咱们能够将同属一个模块的接口定义在一个Controller里。默认状况下,Swagger是以Controller为单位,对接口进行分组管理的。这个分组的元素在Swagger中称为Tag,可是这里的Tag与接口的关系并非一对多的,它支持更丰富的多对多关系。git

默认分组

首先,咱们经过一个简单的例子,来看一下默认状况,Swagger是如何根据Controller来组织Tag与接口关系的。定义两个Controller,分别负责教师管理与学生管理接口,好比下面这样:github

@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是这样组织的:spring

图中标出了Swagger默认生成的Tag与Spring Boot中Controller展现的内容与位置。数组

自定义默认分组的名称

接着,咱们能够再试一下,经过@Api注解来自定义Tag,好比这样:app

@Api(tags = "教师管理")
@RestController
@RequestMapping(value = "/teacher")
static class TeacherController {

    // ...

}

@Api(tags = "学生管理")
@RestController
@RequestMapping(value = "/student")
static class StudentController {

    // ...

}

再次启动应用以后,咱们就看到了以下的分组内容,代码中@Api定义的tags内容替代了默认产生的teacher-controllerstudent-controllerspring-boot

合并Controller分组

到这里,咱们还都只是使用了TagController一一对应的状况,Swagger中还支持更灵活的分组!从@Api注解的属性中,相信聪明的读者必定已经发现tags属性实际上是个数组类型:学习

咱们能够经过定义同名的Tag来汇总Controller中的接口,好比咱们能够定义一个Tag为“教学管理”,让这个分组同时包含教师管理和学生管理的全部接口,能够这样来实现:ui

@Api(tags = {"教师管理", "教学管理"})
@RestController
@RequestMapping(value = "/teacher")
static class TeacherController {

    // ...

}

@Api(tags = {"学生管理", "教学管理"})
@RestController
@RequestMapping(value = "/student")
static class StudentController {

    // ...

}

最终效果以下:this

更细粒度的接口分组

经过@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用户,能够经过以下方式:

file

第二种: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的排序配置没有可选项。它提供了两个配置项:alphamethod,分别表明了按字母表排序以及按方法定义顺序排序。当咱们不配置的时候,改配置默认为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目录:

若是您以为本文不错,欢迎Star支持,您的关注是我坚持的动力!

相关资料

欢迎关注个人公众号:程序猿DD,得到独家整理的学习资源和平常干货推送。
若是您对个人专题内容感兴趣,也能够关注个人博客:didispace.com

相关文章
相关标签/搜索