Spring Boot中使用Swagger2构建强大的RESTful API文档

由于Spring Boot能够快速开发、便捷部署等特性,相信有很大一部分Spring Boot的用户会用来构建RESTful API。而我们构建RESTful API的目的通常都是由于多终端的原因,这些终端会共用很多底层业务逻辑,因此我们会抽象出这样一层来同时服务于多个移动端或者Web前端。

这样一来,我们的RESTful API就有可能要面对多个开发人员或多个开发团队:IOS开发、Android开发或是Web开发等。为了减少与其他团队平时开发期间的频繁沟通成本,传统做法我们会创建一份RESTful API文档来记录所有接口细节,然而这样的做法有以下几个问题:

  • 由于接口众多,并且细节复杂(需要考虑不同的HTTP请求类型、HTTP头部信息、HTTP请求内容等),高质量地创建这份文档本身就是件非常吃力的事,下游的抱怨声不绝于耳。
  • 随着时间推移,不断修改接口实现的时候都必须同步修改接口文档,而文档与代码又处于两个不同的媒介,除非有严格的管理机制,不然很容易导致不一致现象。

为了解决上面这样的问题,本文将介绍RESTful API的重磅好伙伴Swagger2,它可以轻松的整合到Spring Boot中,并与Spring MVC程序配合组织出强大RESTful API文档。它既可以减少我们创建文档的工作量,同时说明内容又整合入实现代码中,让维护文档和修改代码整合为一体,可以让我们在修改代码逻辑的同时方便的修改文档说明。另外Swagger2也提供了强大的页面测试功能来调试每个RESTful API。具体效果如下图所示:

alt=alt=

下面来具体介绍,如果在Spring Boot中使用Swagger2。首先,我们需要一个Spring Boot实现的RESTful API工程,若您没有做过这类内容,建议先阅读
Spring Boot构建一个较为复杂的RESTful APIs和单元测试。

下面的内容我们会以教程样例中的Chapter3-1-1进行下面的实验(Chpater3-1-5是我们的结果工程,亦可参考)。

添加Swagger2依赖

pom.xml中加入Swagger2的依赖

1
2
3
4
5
6
7
8
9
10
11
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger2</artifactId>
<version>2.2.2</version>
</dependency>
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger-ui</artifactId>
<version>2.2.2</version>
</dependency>

创建Swagger2配置类

Application.java同级创建Swagger2的配置类Swagger2

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
@Configuration
@EnableSwagger2
public class Swagger2 {
@Bean
public Docket createRestApi() {
return new Docket(DocumentationType.SWAGGER_2)
.apiInfo(apiInfo())
.select()
.apis(RequestHandlerSelectors.basePackage("com.didispace.web"))
.paths(PathSelectors.any())
.build();
}
private ApiInfo apiInfo() {
return new ApiInfoBuilder()
.title("Spring Boot中使用Swagger2构建RESTful APIs")
.description("更多Spring Boot相关文章请关注:http://blog.didispace.com/")
.termsOfServiceUrl("http://blog.didispace.com/")
.contact("程序猿DD")
.version("1.0")
.build();
}
}

如上代码所示,通过@Configuration注解,让Spring来加载该类配置。再通过@EnableSwagger2注解来启用Swagger2。

再通过createRestApi函数创建Docket的Bean之后,apiInfo()用来创建该Api的基本信息(这些基本信息会展现在文档页面中)。select()函数返回一个ApiSelectorBuilder实例用来控制哪些接口暴露给Swagger来展现,本例采用指定扫描的包路径来定义,Swagger会扫描该包下所有Controller定义的API,并产生文档内容(除了被@ApiIgnore指定的请求)。

添加文档内容

在完成了上述配置后,其实已经可以生产文档内容,但是这样的文档主要针对请求本身,而描述主要来源于函数等命名产生,对用户并不友好,我们通常需要自己增加一些说明来丰富文档内容。如下所示,我们通过@ApiOperation注解来给API增加说明、通过@ApiImplicitParams@ApiImplicitParam注解来给参数增加说明。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
@RestController
@RequestMapping(value="/users") // 通过这里配置使下面的映射都在/users下,可去除
public class UserController {
static Map<Long, User> users = Collections.synchronizedMap(new HashMap<Long, User>());
@ApiOperation(value="获取用户列表", notes="")
@RequestMapping(value={""}, method=RequestMethod.GET)
public List<User> getUserList() {
List<User> r = new ArrayList<User>(users.values());
return r;
}
@ApiOperation(value="创建用户", notes="根据User对象创建用户")
@ApiImplicitParam(name = "user", value = "用户详细实体user", required = true, dataType = "User")
@RequestMapping(value="", method=RequestMethod.POST)
public String postUser(@RequestBody User user) {
users.put(user.getId(), user);
return "success";
}
@ApiOperation(value="获取用户详细信息", notes="根据url的id来获取用户详细信息")
@ApiImplicitParam(name = "id", value = "用户ID", required = true, dataType = "Long")
@RequestMapping(value="/{id}", method=RequestMethod.GET)
public User getUser(@PathVariable Long id) {
return users.get(id);
}
@ApiOperation(value="更新用户详细信息", notes="根据url的id来指定更新对象,并根据传过来的user信息来更新用户详细信息")
@ApiImplicitParams({
@ApiImplicitParam(name = "id", value = "用户ID", required = true, dataType = "Long"),
@ApiImplicitParam(name = "user", value = "用户详细实体user", required = true, dataType = "User")
})
@RequestMapping(value="/{id}", method=RequestMethod.PUT)
public String putUser(@PathVariable Long id, @RequestBody User user) {
User u = users.get(id);
u.setName(user.getName());
u.setAge(user.getAge());
users.put(id, u);
return "success";
}
@ApiOperation(value="删除用户", notes="根据url的id来指定删除对象")
@ApiImplicitParam(name = "id", value = "用户ID", required = true, dataType = "Long")
@RequestMapping(value="/{id}", method=RequestMethod.DELETE)
public String deleteUser(@PathVariable Long id) {
users.remove(id);
return "success";
}
}

完成上述代码添加上,启动Spring Boot程序,访问:http://localhost:8080/swagger-ui.html
。就能看到前文所展示的RESTful API的页面。我们可以再点开具体的API请求,以POST类型的/users请求为例,可找到上述代码中我们配置的Notes信息以及参数user的描述信息,如下图所示。

altalt

API文档访问与调试

在上图请求的页面中,我们看到user的Value是个输入框?是的,Swagger除了查看接口功能外,还提供了调试测试功能,我们可以点击上图中右侧的Model Schema(黄色区域:它指明了User的数据结构),此时Value中就有了user对象的模板,我们只需要稍适修改,点击下方“Try it out!”按钮,即可完成了一次请求调用!

此时,你也可以通过几个GET请求来验证之前的POST请求是否正确。

相比为这些接口编写文档的工作,我们增加的配置内容是非常少而且精简的,对于原有代码的侵入也在忍受范围之内。因此,在构建RESTful API的同时,加入swagger来对API文档进行管理,是个不错的选择。

转载于:https://www.cnblogs.com/xiangjune/p/6639832.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/401274.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

关于公司没有公网IP也没有动态IP,如何远程办公呢?

2019独角兽企业重金招聘Python工程师标准>>> 迫于公司网络环境特殊&#xff0c;没有公网IP地址&#xff0c;也没有动态IP地址&#xff0c;其实就是园区分了一根内网固定IP的网线过来&#xff0c;这两天正巧有同事要外出办公&#xff0c;问题来了&#xff0c;开发环境…

ST_LINK/V2 SWIM和SWD、JTAG下载口说明

LED状态说明 闪烁红色&#xff1a;ST-LINK/V2连接到计算机后&#xff0c;第一次USB枚举过程红色&#xff1a;ST-LINK/V2与计算机已建立连接闪烁绿色/红色&#xff1a;目标板和计算机在进行数据交换绿色&#xff1a;通讯完成橙色&#xff08;红色绿色&#xff09;&#xff1a;通…

Gerrit的用法及与gitlab的区别

Python微信订餐小程序课程视频 https://edu.csdn.net/course/detail/36074 Python实战量化交易理财系统 https://edu.csdn.net/course/detail/35475 来到一个新的团队&#xff0c;开发的代码被同事覆盖了。找同事核实&#xff0c;同事却说根本没有看到我的代码。经过一番沟通…

The 15th UESTC Programming Contest Preliminary H - Hesty Str1ng cdoj1551

地址&#xff1a;http://acm.uestc.edu.cn/#/problem/show/1551 题目&#xff1a; Hesty Str1ng Time Limit: 3000/1000MS (Java/Others) Memory Limit: 65535/65535KB (Java/Others) A chrysanthemum was painted on the second page, and we tried to use the magic pow…

easyui 点滴记录

为什么80%的码农都做不了架构师&#xff1f;>>> 【1.安装】&#xff1a;pip install easygui 【2.常用】 integerbox 交互式输入数字textbox 交互式输入文本ccbox 确认判断boolbox 是否判断multchoicebox 多选条目choicebox 单选条目buttonbox 单选按钮【3.体验一…

IAR切BANK--BANK说明

一、为什么要用到BANK&#xff1f; C51单片机的最大寻址范围为2^1664K&#xff0c;为了突破64K代码的限制&#xff0c;就需要采用C51的切BANK。 二、切BANK的原理 代码地址空间的上半部 ,以重叠BANK0的物理地址空间 , 硬件设计了 n个存储 器页面来存储程序代码 。在任一时刻 …

hdu 4293 Groups DP

http://acm.hdu.edu.cn/showproblem.php?pid4293 题意&#xff1a; 有n个人分成了若干组走在一条林荫道路上&#xff0c;导游为了能够确定人数&#xff0c;要求每个人喊出自己所在的队伍前边有多少人Ai表示,后边有多少人Bi表示&#xff0c;于是我们得到了n条信息。这里面有错误…

IAR切BANK--命令连接器文件xcl格式说明

IAREWARM中段后缀含义 后缀 段类型 含义 AC CONST 绝对地址定位常数 AN DATA 用关键字__no_init声明的绝对地址定位数据 C CONST 常数 I DATA 初始化值为非0的数据 ID CONST 上述数据的初始式 N DATA 未初始化的数据 Z DATA 初始化值为0的数据 ROM用于…

DBA_Oracle Table Partition表分区概念汇总(概念)

2014-06-20 Created By BaoXinjian 一、摘要 有关表分区的一些维护性操作&#xff1a; 注&#xff1a;分区根据具体情况选择。 表分区有以下优点&#xff1a; 1、数据查询&#xff1a;数据被存储到多个文件上&#xff0c;减少了I/O负载&#xff0c;查询速度提高。 2、数据修剪&…

electron打包vue项目

Python微信订餐小程序课程视频 https://edu.csdn.net/course/detail/36074 Python实战量化交易理财系统 https://edu.csdn.net/course/detail/35475 创建项目 点击这里 添加electron-builder 1、在项目目录下运行命令&#xff1a;vue add electron-builder 2、electron-…

Hdu 4293 DP

题意&#xff1a; n个人说自己前面有多少人 后面有多少人 求出说真话人数最多的情况 每个样例有 一个 n 表示n个人 接下来 n 行有a b 表示他前面的人数和后面的人数 思路&#xff1a; 如果已经知道了其中一组的人数~ 就往前找..找在这一组之前与这一组的话不矛盾的最多人数 Ti…

IAR切BANK--程序中的使用

一、在IAR的集成开发环境中实现数据变量定位方法如下三种 1、__no_init char alpha 0x0200; 2、#pragma location 0x0202 const int beta; 3、const int gamma 0x0204 3; 或&#xff1a; 1&#xff09;__no_init int alpha "MYSEGMENT"; //MYSEGMENT段可在…

CSS/CSS3语法新特性笔记

Python微信订餐小程序课程视频 https://edu.csdn.net/course/detail/36074 Python实战量化交易理财系统 https://edu.csdn.net/course/detail/35475 CSS层叠样式表 三大特性 层叠性&#xff1a;相同的样式会覆盖 继承性&#xff1a;属性可向下继承 优先级&#xff1a;范…

C# winform 自定义皮肤制作

最近要做个软件正在做技术准备&#xff0c;由于WINFORM生成的窗体很丑陋&#xff0c;一个好的软件除了功能性很重要外&#xff0c;UI的体验也是不容忽视的。习惯性的在网上搜素了下&#xff0c;换肤控件也有好几款&#xff0c;但是有些用起来不是很好用&#xff0c;好点的也要花…

蓝牙PROFILE

Bluetooth的一个很重要特性&#xff0c;就是所有的Bluetooth产品都无须实现全部 的Bluetooth规范。为了更容易的保持Bluetooth设备之间的兼容&#xff0c;Bluetooth规范中定义了Profile。Profile定义了设备如何实现一种连接或者应用&#xff0c;你可以把Profile理解为连接层或者…

netty系列之:EventLoop,EventLoopGroup和netty的默认实现

Python微信订餐小程序课程视频 https://edu.csdn.net/course/detail/36074 Python实战量化交易理财系统 https://edu.csdn.net/course/detail/35475 目录* 简介 EventLoopGroup和EventLoopEventLoopGroup在netty中的默认实现EventLoop在netty中的默认实现总结 简介 在net…

Oracle安装部署之RedHat安装Oracle11g_R2

硬件配置 内存 &#xff1a;≥1G 硬盘空间&#xff1a;≥10G 上传oracle11g安装包&#xff1a; putty上用wcw用户登录&#xff0c;通过ftp服务上传oracle安装文件到/home/wcw目录下解压 #unzip linux_11gR2_database_1of2.zip #unzip linux_11gR2_database_2of2.zip 检查和安装…

Fans没信心,回家继续修行

今天在CSDN上看了一篇的文章&#xff0c;感觉自己实在是太菜了&#xff0c;以至于对毕业之后从事IT行业没有了任何信心。现在也不清楚&#xff0c;自己能否在it行业混下去。自己的技术实在是一个水啊。8号就要回家了&#xff0c;兄弟姐妹们如果有事情&#xff0c;请发短信至 15…

基于SqlSugar的数据库访问处理的封装,支持多数据库并使之适应于实际业务开发中

Python微信订餐小程序课程视频 https://edu.csdn.net/course/detail/36074 Python实战量化交易理财系统 https://edu.csdn.net/course/detail/35475 在我的各种开发框架中&#xff0c;数据访问有的基于微软企业库&#xff0c;有的基于EFCore的实体框架&#xff0c;两者各有其…

Unity 实现物体破碎效果(转)

感谢网友分享&#xff0c;原文地址&#xff08;How to Make an Object Shatter Into Smaller Fragments in Unity&#xff09;&#xff0c;中文翻译地址&#xff08;Unity实现物体破碎效果&#xff09; In this tutorial I will show you how to create a simple shattering ef…