1 概述
现在一般都是前后端分离的模式,后端开发的接口前端需要使用,此时需要提供接口的说明文档给前端;后端开发的接口,后端自己也要测试,甚至需要提供给专门的测试人员测试,此时也需要有具体的接口说明;如果接口是提供给第三方的,为了降低沟通成本,接口文档也是必须的。
提供文档最常用的是使用swagger,springboot有一度把swagger当推荐引入了内部依赖包中,使用Springfox进行桥接,但从2.6.x版本开始就不再支持Springfox了,需要改用springdoc的方式,本文都是基于springdoc的方式进行提供代码文档。
springdoc的官网:https://springdoc.org/
2 使用springdoc
2.1 引入依赖包
这里使用的springboot是2.7.18,所以要引入的依赖包是springdoc-openapi-ui:
<properties>
<springdoc.version>1.8.0</springdoc.version>
</properties>
<dependency>
<groupId>org.springdoc</groupId>
<artifactId>springdoc-openapi-ui</artifactId>
<version>${springdoc.version}</version>
</dependency>
如果springboot是3.x版本,则应该引入springdoc-openapi-starter-webmvc-ui:
<dependency>
<groupId>org.springdoc</groupId>
<artifactId>springdoc-openapi-starter-webmvc-ui</artifactId>
<version>2.8.9</version>
</dependency>
2.2 用注解添加文档
下面列一些常用的注解,也不建议用很偏门的注解:
注解 |
参数 |
使用说明 |
@Tag |
name:标签的名称,相同名称表示同一组; description:描述; |
一般用在Controller类中,表示把改Controller类的接口文档分到一组,相同的tag归到同一组。 |
@Operation |
summary:用一句话简短说明操作; description:详细说明操作; |
一般放到接口方法上,表示该方法所做的操作说明。 |
@Parameter |
description:对接口参数的说明; required:参数是否必填,默认为false; |
一般用于单个的基本类型参数,表示对接口的参数指定说明。 |
@ParameterObject |
/ |
一般用于对象型的参数,表示对这个对象进行文档说明。 |
@Schema |
description:描述; requiredMode:是否必填,可用RequiredMode枚举; maxLength:最大长度; minContains:最小值; maxContains:最大值; implementation:实现类,多用于枚举; |
一般用于参数对象的类或字段说明。如果字段是枚举,则可以指定implementation,这样可以把枚举的具体值也体现在文档上。 |
2.3 开启文档
在application.properties上加上配置:
server.servlet.context-path=/srvpro
springdoc.api-docs.enabled=true
# springdoc.api-docs.path=${server.servlet.context-path}/v3/api-docs # 默认为/v3/api-docs
springdoc.swagger-ui.enabled=true
# springdoc.swagger-ui.path=${server.servlet.context-path}/swagg
注意:两个都enabled配置都需要为true才能展示文档,文档访问的html路径可以修改。
2.4 例子
@Tag(name = "欢迎Controller", description = "表达欢迎语的接口")
@RestController
public class HelloController {
private Logger logger = LoggerFactory.getLogger(HelloController.class);
@Autowired
private GroupMemberCreator groupMemberCreator;
@Operation(summary = "输出欢迎信息", description = "当输入关键字时,输出带关键字的欢迎信息")
@GetMapping("sayHello")
public String say(@Parameter(description = "欢迎关键字", required = false) @RequestParam("message") String messge) {
logger.info("Access saying hello, message={}", messge);
return "Hello world: " + messge;
}
@PostMapping("createGroupMember")
public GroupMember createGroupMember(@ParameterObject @RequestBody GroupMember member) {
return groupMemberCreator.create(member.getGroupId(), member.getName());
}
}
@Schema(description = "组成员信息")
public class GroupMember {
@Schema(description = "组ID", requiredMode = RequiredMode.REQUIRED)
private Long groupId;
@Schema(description = "组成员名称", maxLength = 64)
private String name;
@Schema(description = "组成员年龄", requiredMode = RequiredMode.NOT_REQUIRED, minContains = 0, maxContains = 200)
private int age;
@Schema(description = "组成员性别", implementation = GroupMemberGender.class)
private GroupMemberGender gender;
// 省略getter方法,注意:无getter方法不会出文档
}
@Schema(description = "组成员性别")
public enum GroupMemberGender {
@Schema(description = "无")
NONE("NONE"),
@Schema(description = "男")
MALE("MALE"),
@Schema(description = "女")
FEMALE("FEMALE");
private String code;
GroupMemberGender(String code) {
this.code = code;
}
}
2.5 访问文档
访问:http://localhost:8080/srvpro/swagger-ui/index.html
展开/sayHello的文档说明:
展开/createGroupMember的说明:
点右上角的“Try it out”可以填写参数字段,然后执行:
这个执行,还贴心地给出了curl的完整命令,可以放到linux的terminal执行。执行的结果也给出了详细的header和body。
3 架构一小步
1、引入文档包依赖,提供写文档基础。
2、使用swagger访问文档,和测试接口。
3、规范:写接口需要在代码中指定说明,以便生成文档。
4、规范:使用@Tag、@Operation、@Parameter、@ParameterObject、@Schema这几个注解提供文档说明。
5、文档在生产环境对外暴露属于漏洞,需要把它们关掉(把enabled项配置成false)。