API文档化
- 前言
- API文档化历史
- 集成Knife4j
- 常用注解
- 基本信息注解
- 分组注解
- 请求方法注解
- 路径注解
- 使用示例
源码地址:请看day07
前言
在现代软件开发中,良好的API文档是团队协作和项目管理中不可或缺的一部分。OpenAPI规范(前身为Swagger)为我们提供了一种标准化的方式来描述和管理RESTful API,Spring Boot通过集成相关工具使得生成和维护API文档变得更加简单和高效。本文将详细介绍如何在Spring Boot项目中利用OpenAPI来自动生成和管理API文档。
API文档化历史
做过API文档化经常可以听到一下几个概念:Swagger
、SpringFox
、SpringDoc
、OpenAPI
、Knife4j
1.Swagger2
是一组围绕 OpenAPI 规范构建的开源工具,可帮助您设计、构建、记录和使用 REST API。主要的 Swagger 工具包括:
Swagger Editor – 基于浏览器的编辑器,您可以在其中编写 OpenAPI 规范。
Swagger UI – 将 OpenAPI规范呈现为交互式 API 文档。
swagger2于17年停止维护,现在最新的版本为 Swagger3(Open Api3)。
2.Open API
OpenAPI
是业界真正的 api 文档标准,其是由 Swagger 来维护的,并被Linux列为api标准,从而成为行业标准,如果想了解
Open API规范,请查看 Swagger Editor 和 OpenAPI规范
3.Swagger3(OpenAPI3)
Swagger 规范已于 2015 年捐赠给 Linux 基金会后改名为 OpenAPI,并定义最新的规范为 OpenAPI 3.0。所以现在的 Swagger 3.0 就是 OpenAPI 3.0。
4.SpringFox
与SpringDoc
SpringFox
: SpringFox 是一个老牌的库,用于将 Spring Boot 应用程序集成到 Swagger(现在称为 OpenAPI)规范中。它通过使用 Swagger 注解来描述 API,并生成符合 OpenAPI 规范的文档。SpringFox 支持Swagger 2.0 版本以及后续的 OpenAPI 3.0 版本。 SpringFox: 使用 @Api、@ApiOperation 等 Swagger 注解
SpringDoc
: SpringDoc是一个相对较新的库,也是用于将 Spring Boot 应用程序集成到 OpenAPI 规范中。它采用更简化的注解,使得在代码中描述 API更为直观。SpringDoc 专注于支持 OpenAPI 3.0 版本。使用 @OpenAPIDefinition、@Operation 等 OpenAPI 注解
5.Knife4j
Knife4j是为Java MVC框架集成Swagger生成Api文档的增强解决方案,前身是swagger-bootstrap-ui,取名kni4j是希望她能像一把匕首一样小巧,轻量,并且功能强悍!(官网)
集成Knife4j
目前只创建了一个微服务,所以本节我们只是在tps-system
中添加Knife4j,后续多个微服务后,我们会进行改进,通过网关聚合所有的Swagger微服务文档。
首先,引用Knife4j的starter,在根Gradle下添加版本号及knife4j引入
knife4jVersion='4.4.0'
implementation "com.github.xiaoymin:knife4j-openapi3-jakarta-spring-boot-starter:${knife4jVersion}"
引入之后,要启用Knife4j的增强功能,可以在配置文件中进行开启,knife4j各种配置可以到官网去看看
部分配置如下:
# springdoc-openapi项目配置
springdoc:
swagger-ui:
path: /swagger-ui.html
tags-sorter: alpha
operations-sorter: alpha
api-docs:
path: /v3/api-docs
group-configs:
- group: 'default'
paths-to-match: '/**'
packages-to-scan: com.tps.cloud.system
# knife4j的增强配置,不需要增强可以不配
knife4j:
enable: true
setting:
language: zh_cn
basic:
enable: true
# Basic认证用户名
username: system
# Basic认证密码
password: 123456
常用注解
在写代码之前,先了解一下OpenAPI 3.0有哪些注解以及各个注解的作用。
基本信息注解
@OpenAPIDefinition
- 描述:用于定义整个 API 文档的基本信息。
- 可用于:类、接口。
- 属性:
info
:指定@Info
注解的对象,用于描述 API 文档的基本信息。
@Info
- 描述:用于定义 API 文档的基本信息。
- 可用于:类、接口。
- 属性:
title
:API 的标题。description
:API 的描述。version
:API 的版本号。termsOfService
:服务条款的 URL。contact
:指定 @Contact 注解的对象,用于描述联系人信息。license
:指定 @License 注解的对象,用于描述许可证信息。
@Contact
- 描述:用于定义 API 文档中的联系人信息。
- 可用于:类、接口。
- 属性:
name
:联系人的名称。
url
:联系人的网址。
email
:联系人的电子邮件地址。
@License
- 描述:用于定义 API 文档中的许可证信息。
- 可用于:类、接口。
- 属性:
name
:许可证的名称。url
:许可证的网址。
分组注解
@Tag
- 描述:用于给 API 分组,用途类似于为 API 文档添加标签。
- 可用于:方法、类、接口。
- 属性:
name
:分组的名称。
请求方法注解
以下注解用于描述 API 的请求方法:
@Operation
- 描述:用于描述 API 的操作。
- 可用于:方法。
- 属性:
summary
:操作的摘要信息。description
:操作的详细描述。tags
:指定 @Tag 注解的对象数组,用于将操作归类到特定的分组。parameters
:指定 @Parameter 注解的对象数组,用于描述操作的输入参数。responses
:指定 @ApiResponse 注解的对象数组,用于描述操作的响应结果。requestBody
:指定 @RequestBody 注解的对象,用于描述操作的请求体。
@Parameter
- 描述:用于描述操作的输入参数。
- 可用于:方法。
- 属性:
name
:参数的名称。in
:参数的位置,可以是 path、query、header、cookie 中的一种。description
:参数的描述。required
:参数是否必需,默认为 false。schema
:指定 @Schema 注解的对象,用于描述参数的数据类型。
@RequestBody
- 描述:用于描述操作的请求体。
- 可用于:方法。
- 属性:
- required:请求体是否必需,默认为 false。
- content:指定 @Content 注解的对象数组,用于描述请求体的内容。
@ApiResponse
- 描述:用于描述操作的响应结果。
- 可用于:方法。
- 属性:
responseCode
:响应的状态码。
-description
:响应的描述。
-content
:指定 @Content 注解的对象数组,用于描述响应的内容。
@Content
- 描述:用于描述请求体或响应的内容。
- 可用于:方法。
- 属性:
mediaType
:内容的媒体类型。schema
:指定 @Schema 注解的对象,用于描述内容的数据类型。
@Schema
- 描述:用于描述数据模型的属性。
- 可用于:方法、类、接口。
- 属性:
title
:数据模型的标题。description
:数据模型的描述。type
:数据模型的类型。format
:数据模型的格式。
路径注解
以下注解用于描述 API 的路径:
@Path
- 描述:用于定义路径参数。
- 可用于:方法。
- 属性:
value
:路径参数的名称。
@PathVariable
- 描述:用于描述路径参数。
- 可用于:方法的参数。
- 属性:
value
:路径参数的名称。
@RequestParam
- 描述:用于描述查询参数。
- 可用于:方法的参数。
- 属性:
value
:查询参数的名称。required
:查询参数是否必需,默认为 false。
@RequestBody
- 描述:用于描述请求体。
- 可用于:方法的参数。
响应注解
以下注解用于描述 API 的响应结果:
@ApiResponse
- 描述:用于描述响应结果。
- 可用于:方法。
- 属性:
responseCode
:响应的状态码。description
:响应的描述。content
:指定 @Content 注解的对象数组,用于描述响应的内容。
@Content
- 描述:用于描述响应结果的内容。
- 可用于:方法。
- 属性:
mediaType
:内容的媒体类型。schema
:指定 @Schema 注解的对象,用于描述内容的数据类型。
@Schema
- 描述:用于描述数据模型的属性。
- 可用于:方法、类、接口。
- 属性:
title
:数据模型的标题。description
:数据模型的描述。type
:数据模型的类型。format
:数据模型的格式。
使用示例
package com.tps.cloud.system.controller;
import com.tps.cloud.group.UpdateGroup;
import com.tps.cloud.response.Result;
import com.tps.cloud.system.dto.SystemUserDto;
import com.tps.cloud.system.service.SystemUserService;
import com.tps.cloud.system.vo.SystemUserVo;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.AllArgsConstructor;
import org.springframework.context.support.MessageSourceAccessor;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
/**
* 用户管理 前端控制器
*/
@RestController
@AllArgsConstructor
@RequestMapping("/system/users")
@Tag(name = "用户管理", description = "用于管理用户信息")
public class SystemUserController {
private final SystemUserService systemUserService;
private final MessageSourceAccessor messages;
@PostMapping
@Operation(summary = "创建用户", description = "创建用户")
public Result<Long> save(@RequestBody @Validated SystemUserDto systemUserDto) {
//验证用户唯一
SystemUserVo systemUserVo=systemUserService.findByUsername(systemUserDto.getUsername());
if(systemUserVo!=null){
return Result.failed(messages.getMessage("SystemUserDto.Username.Exist"));
}
Long id=systemUserService.createUser(systemUserDto);
return Result.ok(id);
}
@PutMapping
@Operation(summary = "更新用户信息", description = "更新用户信息")
public Result<Boolean> update(@RequestBody @Validated({UpdateGroup.class}) SystemUserDto systemUserDto) {
systemUserService.updateUser(systemUserDto);
return Result.ok(true);
}
@GetMapping
@Operation(summary = "根据ID获取用户信息", description = "根据用户ID查询用户的详细信息")
@Parameter(name = "id", description = "用户id", required = true)
public Result<SystemUserVo> getUser(@RequestParam("id") Long id) {
SystemUserVo user = systemUserService.getUser(id);
return Result.ok(user);
}
}
package com.tps.cloud.system.dto;
import com.tps.cloud.group.AddGroup;
import com.tps.cloud.group.UpdateGroup;
import com.tps.cloud.system.constraint.UniqueUsername;
import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.validation.Valid;
import jakarta.validation.constraints.NotBlank;
import lombok.Data;
import java.time.LocalDateTime;
/**
* 用户信息传输类
*/
@Data
public class SystemUserDto {
/**
* 用户id
*/
@Schema(description = "用户id")
private Long id;
/**
* 用户账号
*/
@NotBlank(message = "{SystemUserDto.Username.NotEmpty}")
//@UniqueUsername
@Schema(description = "用户账号")
private String username;
/**
* 密码
*/
@NotBlank(message = "密码不能为空",groups = {AddGroup.class,UpdateGroup.class})
@Schema(description = "密码")
private String password;
/**
* 用户昵称
*/
@Schema(description = "用户昵称")
private String nickname;
/**
* 备注
*/
@Schema(description = "备注")
private String remark;
/**
* 部门id
*/
@Schema(description = "部门id")
private Long deptId;
/**
* 用户邮箱
*/
@Schema(description = "用户邮箱")
private String email;
/**
* 手机号码
*/
@Schema(description = "手机号码")
private String mobile;
/**
* 用户性别
*/
@Schema(description = "用户性别")
private Integer sex;
/**
* 头像地址
*/
@Schema(description = "头像地址")
private String avatar;
/**
* 帐号状态(0正常 1停用)
*/
@Schema(description = "帐号状态")
private Integer status;
/**
* 最后登录IP
*/
@Schema(description = "最后登录IP")
private String loginIp;
/**
* 最后登录时间
*/
@Schema(description = "最后登录时间")
private LocalDateTime loginDate;
/**
* 部门
*/
@Valid
@Schema(description = "部门")
private SystemDeptDto systemDept;
}
重新启动项目,访问http://localhost:8080/doc.html