芋道 Spring Boot API 接口文档 Swagger 入门
摘要: 原创出处 http://www.iocoder.cn/Spring-Boot/Swagger/ 「芋道源码」欢迎转载,保留摘要,谢谢!
- 1. 概述
- 2. 快速入门 Swagger
- 3. 更好看的 Swagger UI 界面
- 4. 更强大的 YApi
- 666. 彩蛋
本文在提供完整代码示例,可见 https://github.com/YunaiV/SpringBoot-Labs 的 lab-24 目录。
原创不易,给点个 Star 嘿,一起冲鸭!
1. 概述
目前,大多数系统都采用前后端分离。在享受前后端分离的好处的同时,接口联调往往成为团队效率的瓶颈,甚至产生前后端的矛盾。简单归结来说,有几方面的原因:
- 问题一,接口设计滞后。 后端团队往往不喜欢 API 接口设计先行,提前和前端沟通好接口。而在开发阶段的中后期,在后端提供 API 接口后,而这些接口和前端的预期有一些偏差,很容易就产生抱怨,特别是项目周期比较紧张的情况下。
- 问题二,接口不规范。 当团队里没有同意明确的接口规范时,又或者代码 Review 做的不是很好的情况下,千奇百怪、各式各样的 API 接口可能就产生了。前端在对接这样的 API 接口,苦不堪言,在一口 mmp 一嘴 fuck xxx 之中,调完接口。
- 问题三,接口文档更新不及时,或者遗忘更新。 因为后端 API 代码和 API 接口在两个地方,我们无法保证提交 API 代码的同时,及时更新文档。有的时候,我们甚至会遗忘更新 API 接口。随着时间的流逝,API 文档和 API 接口不一致的地方越来越多,前端会对 API 接口的信任度越来越低,然后不知道不觉之中,回到原始时代,直接问后端开发 API 是什么样的。
对于问题一和问题二,更多是开发流程上的问题,所以不在本文的范围内。当然话痨的艿艿,还是要给点粗浅的建议,完全拦不住我啊。
- 接口设计先行。设计完成后,后端和前端进行简单沟通,看看是否能够满足诉求。
统一的接口规范。一定要制定统一的接口规范文档,即使比较简陋,也能保证团队的 API 接口相对统一一致。
- 即使错,咱也错的一模一样,而不是千奇百怪。当然,接口规范是无法覆盖到所有的场景的,借助于“接口设计先行”,我们可以提前去 Review 每个接口的设计。
对于问题三,就进入了本文的主角 Swagger 。通过在 API 接口上,添加相应的 Swagger 提供的注解,自动生成 API 文档。酱紫,API 接口和文档就在一起了,从此过上了幸福快乐的生活。
FROM 《RESTful 风格的 Web 服务框架 Swagger》
Swagger 是一个规范和完整的框架,用于生成、描述、调用和可视化 RESTful 风格的 Web 服务。
总体目标是使客户端和文件系统作为服务器以同样的速度来更新。文件的方法、参数和模型紧密集成到服务器端的代码,允许 API 来始终保持同步。Swagger 让部署管理和使用功能强大的 API 从未如此简单。
预览图2. 快速入门 Swagger
示例代码对应仓库:lab-24-apidoc-swagger 。
在本小节,我们来快速入门 Swagger ,可以更加直观的感受到其提供的便利性。
2.1 引入依赖
在
pom.xml
文件中,引入相关依赖。<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.1.3.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>lab-24-apidoc-swagger</artifactId>
<dependencies>
<!-- 实现对 Spring MVC 的自动化配置 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- 引入 Swagger 依赖 -->
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger2</artifactId>
<version>2.9.2</version>
</dependency>
<!-- 引入 Swagger UI 依赖,以实现 API 接口的 UI 界面 -->
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger-ui</artifactId>
<version>2.9.2</version>
</dependency>
</dependencies>
</project>具体每个依赖的作用,胖友自己认真看下艿艿添加的所有注释噢。
2.2 SwaggerConfiguration
因为 Spring Boot 暂未提供 Swagger 内置的支持,所以我们需要自己定义配置类。
在
cn.iocoder.springboot.lab24.apidoc.config
包路径下,创建 SwaggerConfiguration 配置类,用于配置 Swagger 。代码如下:// SwaggerConfiguration.java
@Configuration
@EnableSwagger2 // 标记项目启用 Swagger API 接口文档
public class SwaggerConfiguration {
@Bean
public Docket createRestApi() {
// 创建 Docket 对象
return new Docket(DocumentationType.SWAGGER_2) // 文档类型,使用 Swagger2
.apiInfo(this.apiInfo()) // 设置 API 信息
// 扫描 Controller 包路径,获得 API 接口
.select()
.apis(RequestHandlerSelectors.basePackage("cn.iocoder.springboot.lab24.apidoc.controller"))
.paths(PathSelectors.any())
// 构建出 Docket 对象
.build();
}
/**
* 创建 API 信息
*/
private ApiInfo apiInfo() {
return new ApiInfoBuilder()
.title("测试接口文档示例")
.description("我是一段描述")
.version("1.0.0") // 版本号
.contact(new Contact("芋艿", "http://www.iocoder.cn", "zhijiantianya@gmail.com")) // 联系人
.build();
}
}- 在类上,添加
@EnableSwagger2
注解, 标记项目启用 Swagger API 接口文档。 - 通过
#createRestApi()
方法,创建 Swagger Docket Bean 。每个属性的作用,胖友看看艿艿的注释。大多数情况下,胖友使用这些属性是足够的。不过如果想看看其它配置,胖友可以自己去如下两个类翻翻:- Docket.java
- ApiInfo.java
2.3 Application
创建
Application.java
类,配置@SpringBootApplication
注解即可。代码如下:// Application.java
@SpringBootApplication
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}先暂时不启动项目。等我们添加好 Controller 。
2.4 UserController
在
cn.iocoder.springboot.lab24.apidoc.controller
包路径下,创建 UserController 类,提供用户 API 接口。代码如下:// UserController.java
@RestController
@RequestMapping("/users")
@Api(tags = "用户 API 接口")
public class UserController {
@GetMapping("/list")
@ApiOperation(value = "查询用户列表", notes = "目前仅仅是作为测试,所以返回用户全列表")
public List<UserVO> list() {
// 查询列表
List<UserVO> result = new ArrayList<>();
result.add(new UserVO().setId(1).setUsername("yudaoyuanma"));
result.add(new UserVO().setId(2).setUsername("woshiyutou"));
result.add(new UserVO().setId(3).setUsername("chifanshuijiao"));
// 返回列表
return result;
}
@GetMapping("/get")
@ApiOperation("获得指定用户编号的用户")
@ApiImplicitParam(name = "id", value = "用户编号", paramType = "query", dataTypeClass = Integer.class, required = true, example = "1024")
public UserVO get(@RequestParam("id") Integer id) {
// 查询并返回用户
return new UserVO().setId(id).setUsername(UUID.randomUUID().toString());
}
@PostMapping("add")
@ApiOperation("添加用户")
public Integer add(UserAddDTO addDTO) {
// 插入用户记录,返回编号
Integer returnId = UUID.randomUUID().hashCode();
// 返回用户编号
return returnId;
}
@PostMapping("/update")
@ApiOperation("更新指定用户编号的用户")
public Boolean update(UserUpdateDTO updateDTO) {
// 更新用户记录
Boolean success = true;
// 返回更新是否成功
return success;
}
@PostMapping("/delete")
@ApiOperation(value = "删除指定用户编号的用户")
@ApiImplicitParam(name = "id", value = "用户编号", paramType = "query", dataTypeClass = Integer.class, required = true, example = "1024")
public Boolean delete(@RequestParam("id") Integer id) {
// 删除用户记录
Boolean success = false;
// 返回是否更新成功
return success;
}
}- 相比我们之前使用 SpringMVC 来说,我们在类和接口上,额外增加了 Swagger 提供的注解。
- 从使用习惯上,我比较喜欢先添加 SpringMVC 的注解,再添加 Swagger 的注解。
- 因为已经使用了 Swagger 的注解,所以类和方法上的注释,一般可以删除了,除非有特殊诉求。
- 其中涉及到的 POJO 类,有 UserAddDTO、UserUpdateDTO、UserVO 。
执行 Application 启动项目。然后浏览器访问
http://127.0.0.1:8080/swagger-ui.html
地址,就可以看到 Swagger 生成的 API 接口文档。如下图所示:至此,我们已经完成了 Swagger 的快速入门。不过考虑到胖友能够更好的使用,我们来一个一个注解了解。
2.5 注解
在
swagger-annotations
库中,在io.swagger.annotations
包路径下,提供了我们会使用到的所有 Swagger 注解。Swagger 提供的注解还是比较多的,大多数场景下,只需要使用到我们在 「2.4 UserController」 中用到的注解。2.5.1 @Api
@Api
注解,添加在 Controller 类上,标记它作为 Swagger 文档资源。示例如下:
// UserController.java
@RestController
@RequestMapping("/users")
@Api(tags = "用户 API 接口")
public class UserController {
// ... 省略
}效果如下:
@Api
注解的常用属性,如下:tags
属性:用于控制 API 所属的标签列表。[]
数组,可以填写多个。- 可以在一个 Controller 上的
@Api
的tags
属性,设置多个标签,那么这个 Controller 下的 API 接口,就会出现在这两个标签中。 - 如果在多个 Controller 上的
@Api
的tags
属性,设置一个标签,那么这些 Controller 下的 API 接口,仅会出现在这一个标签中。 - 本质上,
tags
就是为了分组 API 接口,和 Controller 本质上是一个目的。所以绝大数场景下,我们只会给一个 Controller 一个唯一的标签。例如说,UserController 的tags
设置为"用户 API 接口"
。
- 可以在一个 Controller 上的
@Api
注解的不常用属性,如下:produces
属性:请求请求头的可接受类型( Accept )。如果有多个,使用,
分隔。consumes
属性:请求请求头的提交内容类型( Content-Type )。如果有多个,使用,
分隔。protocols
属性:协议,可选值为"http"
、"https"
、"ws"
、"wss"
。如果有多个,使用,
分隔。authorizations
属性:授权相关的配置,[]
数组,使用@Authorization
注解。hidden
属性:是否隐藏,不再 API 接口文档中显示。@Api
注解的废弃属性,不建议使用,有value
、description
、basePath
、position
。2.5.2 @ApiOperation
@ApiOperation
注解,添加在 Controller 方法上,标记它是一个 API 操作。示例如下:
// UserController.java
@GetMapping("/list")
@ApiOperation(value = "查询用户列表", notes = "目前仅仅是作为测试,所以返回用户全列表")
public List<UserVO> list() {
// 查询列表
List<UserVO> result = new ArrayList<>();
result.add(new UserVO().setId(1).setUsername("yudaoyuanma"));
result.add(new UserVO().setId(2).setUsername("woshiyutou"));
result.add(new UserVO().setId(3).setUsername("chifanshuijiao"));
// 返回列表
return result;
}效果如下:
@ApiOperation
注解的常用属性,如下:value
属性:API 操作名。notes
属性:API 操作的描述。@ApiOperation
注解的不常用属性,如下:tags
属性:和@API
注解的tags
属性一致。nickname
属性:API 操作接口的唯一标识,主要用于和第三方工具做对接。httpMethod
属性:请求方法,可选值为GET
、HEAD
、POST
、PUT
、DELETE
、OPTIONS
、PATCH
。因为 Swagger 会解析 SpringMVC 的注解,所以一般无需填写。produces
属性:和@API
注解的produces
属性一致。consumes
属性:和@API
注解的consumes
属性一致。protocols
属性:和@API
注解的protocols
属性一致。authorizations
属性:和@API
注解的authorizations
属性一致。hidden
属性:和@API
注解的hidden
属性一致。response
属性:响应结果类型。因为 Swagger 会解析方法的返回类型,所以一般无需填写。responseContainer
属性:响应结果的容器,可选值为List
、Set
、Map
。responseReference
属性:指定对响应类型的引用。这个引用可以是本地,也可以是远程。并且,当设置了它时,会覆盖response
属性。说人话,就是可以忽略这个属性,哈哈哈。responseHeaders
属性:响应头,[]
数组,使用@ResponseHeader
注解。code
属性:响应状态码,默认为 200 。extensions
属性:拓展属性,[]
属性,使用@Extension
注解。ignoreJsonView
属性:在解析操作和类型,忽略 JsonView 注释。主要是为了向后兼容。@ApiOperation
注解的废弃属性,不建议使用,有position
。2.5.3 @ApiImplicitParam
@ApiImplicitParam
注解,添加在 Controller 方法上,声明每个请求参数的信息。示例如下:
// UserController.java
@PostMapping("/delete")
@ApiOperation(value = "删除指定用户编号的用户")
@ApiImplicitParam(name = "id", value = "用户编号", paramType = "query", dataTypeClass = Integer.class, required = true, example = "1024")
public Boolean delete(@RequestParam("id") Integer id) {
// 删除用户记录
Boolean success = false;
// 返回是否更新成功
return success;
}效果如下:
@ApiImplicitParam
注解的常用属性,如下:name
属性:参数名。value
属性:参数的简要说明。required
属性:是否为必传参数。默认为false
。dataType
属性:数据类型,通过字符串 String 定义。dataTypeClass
属性:数据类型,通过dataTypeClass
定义。在设置了dataTypeClass
属性的情况下,会覆盖dataType
属性。推荐采用这个方式。paramType
属性:参数所在位置的类型。有如下 5 种方式:"path"
值:对应 SpringMVC 的@PathVariable
注解。- 【默认值】
"query"
值:对应 SpringMVC 的@PathVariable
注解。 "body"
值:对应 SpringMVC 的@RequestBody
注解。"header"
值:对应 SpringMVC 的@RequestHeader
注解。"form"
值:Form 表单提交,对应 SpringMVC 的@PathVariable
注解。- ©著作权归作者所有:来自51CTO博客作者mb5ff80520dfa04的原创作品,如需转载,请注明出处,否则将追究法律责任
更多相关文章
- 芋道 Spring Boot JPA 入门(三)之基于注解查询
- 芋道 Spring Boot MyBatis 入门(二)之 MyBatis + 注解
- SpringBoot 中 @SpringBootApplication注解背后的三体结构探秘
- Spring 注解编程之模式注解
- 使用类型注解让 Python 代码更易读
- 常用的php正则表达及语法注解总结
- 如何直接访问php实例对象的private属性
- php通过反射修改Exception实例的message属性
随机推荐