相信无论是前端还是后端开发,都或多或少地被接口文档折磨过。前端经常抱怨后端给的接口文档与实际情况不一致。后端又觉得编写及维护接口文档会耗费不少精力,经常来不及更新。其实无论是前端调用后端,还是后端调用后端,都期望有一个好的接口文档。但是这个接口文档对于程序员来说,就跟注释一样,经常会抱怨别人写的代码没有写注释,然而自己写起代码起来,最讨厌的,也是写注释。所以仅仅只通过强制来规范大家是不够的,随着时间推移,版本迭代,接口文档往往很容易就跟不上代码了

Swagger简介
Swagger 是什么?有什么用?
Swagger 是一个 API 文档维护组织,后来成为了 Open API 标准的主要定义者,现在最新的版本为 17 年发布的 Swagger3。
Swagger 是一个规范和完整的框架,用于生成可视化 RESTful 风格的 Web 服务。
总的来说Swagger 是一个用于生成、描述和调用 RESTful 接口的 Web 服务。通俗的来讲,Swagger 就是将项目中所有(想要暴露的)接口展现在页面上,并且可以进行接口调用和测试的服务
PS:Swagger 遵循了 OpenAPI 规范,OpenAPI 是 Linux 基金会的一个项目,试图通过定义一种用来描述 API 格式或 API 定义的语言,来规范 RESTful 服务开发过程。
从上述 Swagger 定义我们不难看出 Swagger 有以下 3 个重要的作用:
- 将项目中所有的接口展现在页面上,这样后端程序员就不需要专门为前端使用者编写专门的接口文档
- 当接口更新之后,只需要修改代码中的 Swagger 描述就可以实时生成新的接口文档了,从而规避了接口文档老旧不能使用的问题
- 通过 Swagger 页面,我们可以直接进行接口调用,降低了项目开发阶段的调试成本
Swagger 使用
与 swagger2 相比新版的 swagger3 配置更少,使用更加方便,本篇文章通过介绍 swagger 3,可以很方便的生成 api 文档。
如果想要将 Swagger 文档集成到 Spring 中,目前有两个开源项目可供开发者选择,一个是 SpringFox,另一个是 SpringDoc,这两个项目都是由 Spring 社区来维护的,在 Swagger 2.0 时代,SpringFox 是主流,但是随着 Swagger 3.0 版本发布之后,SpringDoc 对最新版本的兼容性更好,而且 SpringDoc 支持 Swagger 页面 Oauth2 登录,因此使用 SpringDoc 是更好的选择。
向 pom.xml 文件中添加如下依赖:
<dependency>
<groupId>org.springdoc</groupId>
<artifactId>springdoc-openapi-ui</artifactId>
<version>1.5.4</version>
</dependency>
创建 SpringDocSwaggerConfig.java 文件(例如如下)
package com.file.config.openapi;
import io.swagger.v3.oas.models.Components;
import io.swagger.v3.oas.models.OpenAPI;
import io.swagger.v3.oas.models.info.Contact;
import io.swagger.v3.oas.models.info.Info;
import io.swagger.v3.oas.models.info.License;
import io.swagger.v3.oas.models.security.SecurityRequirement;
import io.swagger.v3.oas.models.security.SecurityScheme;
import org.springdoc.core.GroupedOpenApi;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class SpringDocSwaggerConfig{
private static final String headerName = "Authorization"; // 请求参数名 默认Authorization
@Bean
public GroupedOpenApi ignoreApi() {
// 白名单APi
String[] paths = {"/user/login"};
return GroupedOpenApi.builder()
.group("ignore")
.pathsToMatch(paths)
.build();
}
@Bean
public GroupedOpenApi userApi() {
String[] defaultPaths = {"/**"};
// 上述白名单APi
String[] ignorePaths = {"/user/login"};
return GroupedOpenApi.builder()
.group("user")
.addOperationCustomizer((operation, handlerMethod) -> {
operation.addSecurityItem(new SecurityRequirement().addList(headerName));
return operation;
})
.pathsToMatch(defaultPaths)
.pathsToExclude(ignorePaths)
.build();
}
@Bean
public OpenAPI customOpenAPI() {
Components components = new Components();
//添加右上角的统一安全认证
components.addSecuritySchemes(headerName,
new SecurityScheme()
.type(SecurityScheme.Type.APIKEY)
.scheme("Bearer")
.name(headerName)
.in(SecurityScheme.In.HEADER)
.description("请求头Token")
);
return new OpenAPI()
.components(components)
.info(apiInfo());
}
/**
* API 信息
* @return
*/
private Info apiInfo() {
Contact contact = new Contact();
contact.setEmail("280668200@qq.com");
contact.setName("Lehman");
contact.setUrl("https://lehman.top");
return new Info()
.title("追风网盘-swagger文档")
.version("v1.0.0")
.contact(contact)
.description("基于Spring Boot 2 + VUE CLI@3框架开发的分布式文件管理系统")
.license(new License().name("Apache 2.0").url("http://springdoc.org"));
}
}
注解介绍
@Tag 注解
该注解可以用来类或方法上,当作用在方法是用来定义单个操作,当作用在类上代表所有操作。
属性 | 描述 |
---|---|
name | 标签名 |
description | 这里可以做一个简短的描述 |
externalDocs | 添加一个扩展文档 |
extensions | 可选的扩展列表 |
@Operation 注解
注释可用于将资源方法定义为 OpenAPI 操作,在该注解中也可以定义该操作的其他属性。
属性 | 描述 |
---|---|
method | HTTP 请求方法 |
tags | 按照资源对操作进行逻辑分组 |
summary | 提供此操作的简要说明。 |
description | 对操作的详细描述 |
requestBody | 与操作关联的请求报文 |
parameters | 一个可选的参数数组 |
responses | 执行此操作返回的可能响应的列表 |
deprecated | 允许将操作标记为已弃用 |
security | 可用于此操作的安全机制的声明 |
@Schema 注解
该注解用来定义模型,主要用来定义模型类及模型的属性,请求和响应的内容、报文头等
属性 | 描述 |
---|---|
not | 提供用于禁止匹配属性的 java 类。 |
name | 用于描述模型类或属性的名称 |
title | 用于描述模型类的标题 |
maximum | 设置属性的最大数值。 |
minimum | 设置属性的最小数值。 |
maxLength | 设置字符串值的最大长度。 |
minLength | 设置字符串值的最大小度。 |
pattern | 值必须满足的模式。 |
required | 是否必输 |
description | 描述 |
nullable | 如果为 true 则可能为 null。 |
example | 使用示例 |
Controller添加注解(示例如下)
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
@Tag(name = "user", description = "该接口为用户接口,主要做用户登录,注册和校验token")
@Slf4j
@RestController
@RequestMapping("/user")
public class UserController {
...
@Operation(summary = "用户注册", description = "注册账号", tags = {"user"})
@PostMapping(value = "/register")
@ResponseBody
public RestResult<String> addUser(@RequestBody RegisterDTO registerDTO) {
...
}
@Operation(summary = "用户登录", description = "用户登录认证后才能进入系统", tags = {"user"})
@GetMapping("/login")
@ResponseBody
public RestResult<LoginVO> userLogin(String telephone, String password) {
...
}
@Operation(summary = "检查用户登录信息", description = "验证token的有效性", tags = {"user"})
@GetMapping("/checkuserlogininfo")
@ResponseBody
public RestResult<User> checkToken(@RequestHeader("token") String token) {
}
}
实体类添加注解(示例如下)
import io.swagger.v3.oas.annotations.media.Schema;
import java.io.Serializable;
/**
* <p>
* 用户表
* </p>
*
* @author Lehman
* @since 2021-08-07
*/
@Schema(description="用户Object")
public class User extends Model<User> {
private static final long serialVersionUID = 1L;
/**
* 用户ID
*/
@TableId(value = "user_id", type = IdType.ASSIGN_UUID)
private String userId;
/**
* 昵称
*/
@Schema(description="昵称")
private String nickName;
/**
* 用户名
*/
@Schema(description="用户名")
private String username;
/**
* 密码
*/
@Schema(description="密码")
private String password;
}
查看效果
点击 run 启动项目,在控制台查看项目启动成功之后,在项目的地址后面追加 /swagger-ui.html 查看效果,如下图:
其中具体操作和信息请结合官网文档食用
knife4j
从上图可以看出该模型的具体信息及其字段含义,整个文档在开发过程已经满足日常使用的要求,但是整体文档风格及排版不太符合大多数人的视觉体验,甚至有人觉得它丑,这个因人而异,因此我可以使用一款美化工具 knife4j,来美化该文档。
knife4j 在最新版本已经基本完全兼容了 springdoc-openapi-ui,因此在替换的时候将依赖替换掉就可以了,打开 pom.xml 文件,删除掉之前的 springdoc-openapi-ui 依赖,添加如下依赖:
<dependency>
<groupId>com.github.xiaoymin</groupId>
<artifactId>knife4j-spring-boot-starter</artifactId>
<version>3.0.2</version>
</dependency>
OpenApiConfig.java 配置文件中修改为如下配置:
package com.wind.common.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import springfox.documentation.builders.ApiInfoBuilder;
import springfox.documentation.builders.PathSelectors;
import springfox.documentation.builders.RequestHandlerSelectors;
import springfox.documentation.service.ApiInfo;
import springfox.documentation.spi.DocumentationType;
import springfox.documentation.spring.web.plugins.Docket;
@Configuration
public class OpenApiConfig {
@Bean(value = "indexApi")
public Docket indexApi() {
return new Docket(DocumentationType.OAS_30)
.groupName("网站前端接口分组").apiInfo(apiInfo())
.select()
.apis(RequestHandlerSelectors.basePackage("com.wind.disk.controller"))
.paths(PathSelectors.any())
.build();
}
private ApiInfo apiInfo() {
return new ApiInfoBuilder()
.title("追风云盘 API")
.description("基于springboot + vue 框架开发的Web文件系统,旨在为用户提供一个简单、方便的文件存储方案,能够以完善的目录结构体系,对文件进行管理 。")
.version("1.0")
.build();
}
}
修改完成之后,重新启动项目,在地址栏之后添加 /doc.html 即可访问文档,如下图:
One comment
博主真是太厉害了!!!