原文链接:

简介

Swagger 官网是这么描述它的:The Best APIs are Built with Swagger Tools

Swagger 是一套基于 OpenAPI 规范构建的开源工具,可以帮助我们设计、构建、记录以及使用 Rest API。Swagger 主要包含了以下三个部分:

  1. Swagger Editor:基于浏览器的编辑器,我们可以使用它编写我们 OpenAPI 规范。
  2. Swagger UI:它会将我们编写的 OpenAPI 规范呈现为交互式的 API 文档,后文我将使用浏览器来查看并且操作我们的 Rest API。
  3. Swagger Codegen:它可以通过为 OpenAPI(以前称为 Swagger)规范定义的任何 API 生成服务器存根和客户端 SDK 来简化构建过程。

Spring Boot 使得开发 RESTful 服务变得简单。那么编写 Spring Boot 接口,为何要用 Swagger 呢?

  • 代码改变,文档就会改变。只需要少量的注释,Swagger 就可以根据代码自动生成 API 文档。
  • Swagger UI 是一份交互式的 API 文档,可以直接在 Web 界面调用 API。这里有一份 Swagger UI 的 Live Demo,看看官方是怎么写 RESTful API 的。

添加依赖

pom.xml 引入 Swagger 相关的依赖:

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

使用 property 定义了 Swagger 的版本,因此还需要添加:

  1. <swagger.version>2.9.2</swagger.version>

依赖说明:

  • springfox-swagger2 Swagger 的 Java 实现
  • springfox-swagger-ui Swagger UI 页面的依赖

Swagger 配置类

使用注解 @Configuration 编写 Swagger 配置类—— SwaggerConfig

新建 config 的包,创建 SwaggerConifg 的配置类:

  1. //通过@Configuration注解,让Spring来加载该类配置
  2. @Configuration
  3. //通过@EnableSwagger2注解来启用Swagger2
  4. @EnableSwagger2
  5. //@ConditionalOnExpression 为Spring的注解,用户是否实例化本类,用于是否启用Swagger的判断(生产环境需要屏蔽Swagger)
  6. @ConditionalOnExpression("${swagger.enable:true}")
  7. public class SwaggerConfig {
  8. // select()函数返回一个ApiSelectorBuilder实例用来控制哪些接口暴露给Swagger来展现,本例采用指定扫描的包路径来定义,
  9. // Swagger会扫描该包下所有Controller定义的API,并产生文档内容(除了被@ApiIgnore指定的请求)
  10. @Bean
  11. public Docket createRestApi() {
  12. // apiInfo()用来创建该Api的基本信息(这些基本信息会展现在文档页面中
  13. ApiInfo apiInfo = new ApiInfoBuilder()
  14. .title("标题: Spring Boot 项目集成 Swagger 示例文档")
  15. .description("描述: 我的博客地址是 https://michael728.github.io")
  16. .termsOfServiceUrl("https://michael728.github.io/")
  17. .version("1.0")
  18. .build();
  19. Docket docket = new Docket(DocumentationType.SWAGGER_2)
  20. .apiInfo(apiInfo)
  21. // select()函数返回一个ApiSelectorBuilder实例
  22. .select()
  23. // 决定了暴露哪些接口给 Swagger
  24. .paths(regex("/api/.*"))
  25. .build()
  26. .useDefaultResponseMessages(false)
  27. .glo
  28. return docket;
  29. }
  30. }

说明:

  • @Configuration 是告诉 Spring Boot 需要加载这个配置类;
  • @EnableSwagger2 是启用 Swagger2,没加的话,就看不到效果了;
  • ApiInfo 对象用来设置一些文档的版本号、联系人邮箱、网站、版权、开源协议等等信息(这些基本信息会展现在文档页面中)。并使用 Docket.apiInfo() 方法来设置;
  • Docket 上增加筛选。提供了 apis()paths() 两个方法帮助我们在不同级别上过滤接口:
    • apis() 这种方式我们可以指定包名的方式,让 Swagger 只去某些包下面扫描;
    • paths() 这种方式可以通过筛选 API 的 url 来进行筛选;
  • @ConditionalOnExpression("${swagger.enable:true}") 这个注解控制了是否启用 Swagger,我们需要在 appplication.properties 中加上 swagger.enable=true

编写控制器类——Controller 类

我们先介绍一下在用 Swagger 时的常用注解:

  • @API 类的注解,可以给控制器增加描述和标签信息。用在请求的类上,代表了这个类是 Swagger 的资源

    • tags:控制器标签,对该类进行「分类」,参数是个字符串数组,如果配置了多个值,会在多个分类中看到;
    • value:该参数没什么意义,在 UI 界面上并不显示,可不用配置
  • @ApiModel 类注解,对 API 涉及的对象做描述,可用于响应实体类,说明实体作用
    • value Model 展示时的名称,默认是 实体类的名称,比如 UserEntity
    • description 实体类的描述

类成员变量的的注解:

  • @ApiModelProperty 用在实体类的属性上

    • value 属性字段描述;
    • required 参数是否必选;
    • name 重写字段名称;
    • dataType 重写字段类型;
    • allowEmptyValue 是否允许为空;
    • allowbleValues 该字段允许的值。当我们 API 某个参数为枚举类型时,使用这个参数就可以清楚高速 API 使用者能允许传入的值

方法的注解:

  • @ApiOperation 描述方法的用途,用来展开对接口的描述

    • value 接口简要描述;
    • notes 接口发布说明,详细描述;
  • @ApiImplicitParams 用于描述接口的非对象参数集,一般与 @ApiImplicitParams 组合使用
  • @ApiImplicitParam 描述参数信息
    • value 参数意义的描述
    • name 参数名字;
    • required 默认 false,参数是否必传
    • dataType 参数数据类型,只作为标志说明,并没有实际验证
      • Long
      • String
    • paramType 参数类型,表示参数放在哪里
      • query,默认值,Query String 的方式传参,请求参数的获取:@RequestParam
      • path 路径参数,请求参数的获取:@PathVariable
      • header 请求参数的获取:@RequestHeader
  • @PathVariable 路径参数,给类似 @GetMappIng("/user/{id}") 参数通过路径传入

其他:

  • @ApiIgnore:用于类或者方法上,屏蔽接口不被显示在页面上;
  • @Profile({"dev","test"}):用于配置类上,表示对什么环境启用;
  • @ApiParam 不能直接用在方法上,而是用在方法的形参定义中,下文会有示例;

实体类示例:

  1. @Data
  2. @ApiModel(value = "用户实体")
  3. public class UserEntity {
  4. public static final long serialVersionUID = 1L;
  5. @ApiModelProperty(value = "用户 id")
  6. private int id;
  7. @ApiModelProperty(value = "用户名", required = true)
  8. private String userName;
  9. @ApiModelProperty(value = "密码" )
  10. private String passWord;
  11. @ApiModelProperty(value = "性别")
  12. private UserSexEnum userSex;
  13. @ApiModelProperty(value = "昵称" )
  14. private String nickName;
  15. public UserEntity(Integer id, String userName, String passWord) {
  16. this.id = id;
  17. this.userName = userName;
  18. this.passWord = passWord;
  19. }
  20. }

下面是一个控制类的示例:

  1. @RestController
  2. @RequestMapping("/api/v1/")
  3. @Api(tags = {"用户相关接口"}, value = "用户模块")
  4. public class UserController {
  5. // 模拟数据库
  6. public static List<UserEntity> users = new ArrayList<>();
  7. static {
  8. UserEntity user1 = new UserEntity(1, "michael", "123");
  9. UserEntity user2 = new UserEntity(2, "qq", "123");
  10. UserEntity user3 = new UserEntity(3, "hh", "123");
  11. users.add(user1);
  12. users.add(user2);
  13. users.add(user3);
  14. }
  15. @ApiOperation(value = "获取用户列表", notes = "获取全部用户信息")
  16. @RequestMapping(value = "/users", method = RequestMethod.GET)
  17. public List<UserEntity> getUsers() {
  18. return users;
  19. }
  20. @ApiOperation(value = "查询单用户", notes = "根据用户id 查询其信息")
  21. @ApiImplicitParam(name = "id", value = "用户id", paramType = "query", required = true)
  22. @GetMapping("/user/{id}")
  23. public UserEntity getUser(@PathParam("id") int id) {
  24. UserEntity user = users.get(id);
  25. return user;
  26. }
  27. @ApiOperation(value = "存储用户信息", notes = "存储用户详细信息")
  28. @RequestMapping(value = "/user", method = RequestMethod.POST)
  29. public UserEntity saveUser(@ApiParam(value = "用户信息", required = true)
  30. @RequestBody UserEntity user) {
  31. users.add(user);
  32. return user;
  33. }
  34. @ApiOperation(value = "删除用户", notes = "根据用户id删除用户信息")
  35. @ApiImplicitParams({
  36. @ApiImplicitParam(name = "id", value = "用户id", required = true, paramType = "path")
  37. })
  38. @RequestMapping(value = "/user/{id}", method = RequestMethod.DELETE)
  39. public int deleteUser(@PathVariable("id") int id) {
  40. users.remove(id);
  41. return id;
  42. }
  43. @ApiOperation(value = "更新用户信息", notes = "更新用户的个人信息")
  44. @PutMapping("/user/")
  45. public UserEntity updateUser(@RequestBody UserEntity user) {
  46. int id = user.getId();
  47. UserEntity oldUser = users.get(id);
  48. users.set(id, user);
  49. return user;
  50. }
  51. }

启动

启动应用,访问 localhost:8080/swagger-ui.html 可以访问到 Swagger UI,可以点击 Try it out 按钮,调用 API:

页面上还会有一个 Models 的分类。Swagger UI 会根据我们在实体上使用的 @ApiModel@ApiModelProperty 注解来自动补充实体以及其属性的描述和备注。

示例代码

One More Thing

Web API 的风格

开发 API,先了解一下有哪些 Web API 的风格吧:

  • RPC:RPC 面向过程,RPC 形式的 API 组织形态是类和方法,API 的命名往往是一个动词,比如 GetUserInfo,CreateUser;
  • REST:REST 面向资源,也是下文将要介绍的一种 API 风格;
  • GraphQL:就是面向数据查询,采用GraphQL,甚至不需要有任何的接口文档,在定义了Schema之后,服务端实现Schema,客户端可以查看Schema,然后构建出自己需要的查询请求来获得自己需要的数据

REST

上文提到了 RESTful API 的概念,我觉得,不如趁机了解一下。因为在实际的项目中发现,并不是每个 Spring Boot 的开发人员都能意识到开发的 API 要尽量符合 RESTful 规则的。REST 实际上只是一种设计风格,它并不是标准。

术语:

  • Endpoint 终点,可以理解为路径,表示 API 的具体网址。
  • API(Application Programming Interface),应用程序编程接口
  • RESTRepresentational State Transfer 的缩写。如果一个架构符合 REST 原则,就称它为 RESTful 架构。RESTful API 就是 REST 风格的 API
    • Resource:资源,即数据。
    • Representational:某种表现形式,比如用 JSON,XML,JPEG 等;
    • State Transfer:状态变化。通过 HTTP 动词实现

在 RESTful 架构中,每个网址代表一种资源(resource),所以网址中不能有动词,只能有名词,而且所用的名词往往与数据库的表格名对应。

资源的操作

RESTful 的核心思想就是,客户端发出的数据操作指令都是"动词 + 宾语"的结构。比如,GET /articles 这个命令,GET 是动词,/articles 是宾语。

对于资源的具体操作类型,由 HTTP 动词表示(括号里是对应的 SQL 命令):

  • GET(SELECT):从服务器取出资源(一项或多项)。
  • POST(CREATE):在服务器新建一个资源。
  • PUT(UPDATE):在服务器更新资源(客户端提供改变后的完整资源)。
  • PATCH(UPDATE):在服务器更新资源(客户端提供改变的属性)。
  • DELETE(DELETE):从服务器删除资源

还有两个不常用的 HTTP 动词:

  • HEAD:获取资源的元数据。
  • OPTIONS:获取信息,关于资源的哪些属性是客户端可以改变的

知乎上的一个回答,我觉得很精辟:

  • 看 Url 就知道要什么
  • 看 http method 就知道干什么
  • 看 http status code 就知道结果如何

一位答主给出的示例:

  1. GET /rest/api/getDogs --> GET /rest/api/dogs 获取所有小狗狗
  2. GET /rest/api/addDogs --> POST /rest/api/dogs 添加一个小狗狗
  3. GET /rest/api/editDogs/:dog_id --> PUT /rest/api/dogs/:dog_id 修改一个小狗狗
  4. GET /rest/api/deleteDogs/:dog_id --> DELETE /rest/api/dogs/:dog_id 删除一个小狗狗

信息过滤 Filtering

如果记录数量很多,服务器不可能都将它们返回给用户。API 应该提供参数,过滤返回结果

  • ?limit=10:指定返回记录的数量
  • ?offset=10:指定返回记录的开始位置。
  • ?page=2&per_page=100:指定第几页,以及每页的记录数

参考

API 介绍

欢迎关注个人公众号 「iPlayMichael」

Spring Boot 集成 Swagger 生成 RESTful API 文档的更多相关文章

  1. Spring Boot 集成Swagger2生成RESTful API文档

    Swagger2可以在写代码的同时生成对应的RESTful API文档,方便开发人员参考,另外Swagger2也提供了强大的页面测试功能来调试每个RESTful API. 使用Spring Boot可 ...

  2. Spring Boot学习笔记 - 整合Swagger2自动生成RESTful API文档

    1.添加Swagger2依赖 在pom.xml中加入Swagger2的依赖 <!--swagger2--> <dependency> <groupId>io.spr ...

  3. Spring Boot中使用Swagger2构建API文档

    程序员都很希望别人能写技术文档,自己却很不愿意写文档.因为接口数量繁多,并且充满业务细节,写文档需要花大量的时间去处理格式排版,代码修改后还需要同步修改文档,经常因为项目时间紧等原因导致文档滞后于代码 ...

  4. springboot集成swagger2构建RESTful API文档

    在开发过程中,有时候我们需要不停的测试接口,自测,或者交由测试测试接口,我们需要构建一个文档,都是单独写,太麻烦了,现在使用springboot集成swagger2来构建RESTful API文档,可 ...

  5. 使用Swagger2Markup归档swagger生成的API文档

    文章出处: http://blog.didispace.com/swagger2markup-asciidoc/ 说明 项目中使用Swagger之后,我们能够很轻松的管理API文档,并非常简单的模拟接 ...

  6. Golang使用swaggo自动生成Restful API文档

    #关于Swaggo 相信很多程序猿和我一样不喜欢写API文档.写代码多舒服,写文档不仅要花费大量的时间,有时候还不能做到面面具全.但API文档是必不可少的,相信其重要性就不用我说了,一份含糊的文档甚至 ...

  7. Spring Boot 集成 Swagger生成接口文档

    目的: Swagger是什么 Swagger的优点 Swagger的使用 Swagger是什么 官网(https://swagger.io/) Swagger 是一个规范和完整的框架,用于生成.描述. ...

  8. Spring Boot中使用Swagger2生成RESTful API文档(转)

    效果如下图所示: 添加Swagger2依赖 在pom.xml中加入Swagger2的依赖 <!-- https://mvnrepository.com/artifact/io.springfox ...

  9. 如何生成RestFul Api文档

    Web API文档工具列表Swagger ——Swagger框架可以通过代码生成漂亮的在线API,甚至可以提供运行示例.支持Scala.Java.Javascript.Ruby.PHP甚至 Actio ...

随机推荐

  1. Predictive Analysis in Network Function Virtualization

    摘要 网络功能虚拟化(NFV)体系结构的最新部署获得了极大的关注.虚拟化虽然带来了诸如降低成本和简化网络功能部署之类的好处,但它增加了附加层,从而降低了较低层故障的透明度.为了改善虚拟网络功能(VNF ...

  2. 【转】HTTP 协议的历史演变和设计思路

    一.HTTP/0.9 HTTP 是基于 TCP/IP 协议的应用层协议.它不涉及数据包(packet)传输,主要规定了客户端和服务器之间的通信格式,默认使用80端口. 最早版本是1991年发布的0.9 ...

  3. 关于SpringCloud、SpringBoot简单讲解

     什么是Spring Boot 用我的话来理解,Spring Boot就是整合了框架的框架,它让一切依赖都变得有序简单,你不用操心A.jar是什么版本,又依赖哪些版本的jar,它默认配置了很多框架的使 ...

  4. axios post 400 状态码

    1.400状态码 400的主要有两种形式: (1).bad request意思是“错误的请求": (2).invalid hostname意思是"不存在的域名”.   2.axio ...

  5. 以太坊公链Geth同步

    1.安装所需基础工具 yum update -y && yum install git wget bzip2 vim gcc-c++ ntp epel-release nodejs c ...

  6. Maven构建报错问题解决

    [ERROR] Failed to execute goal on project zepeto-admin: Could not resolve dependencies -SNAPSHOT: Fa ...

  7. 如何开发一个npm包并发布到npm中央仓库

    转自: https://liaolongdong.com/2019/01/24/publish-public-npm.html 如何开发一个npm包并发布到npm中央仓库需求背景:平时在项目工作中可能 ...

  8. 品优购商城项目(五)消息中间件 ActiveMQ

    消息中间件用于降低各个项目模块的耦合,适用于不需要等待返回消息才能进入下一个业务环节的模块,以及实时要求性不高的业务模块. 一.JMS JMS(Java Messaging Service)是Java ...

  9. java开发异常Exception集锦

    背景:整理开发过程中的异常问题 java.lang.Exception: No tests found matching 一般出现在新导入的工程中.在sts中通过open project的方式导入工程 ...

  10. OpenJudge 4120 硬币

    总时间限制: 1000ms 内存限制: 262144kB 描述 宇航员Bob有一天来到火星上,他有收集硬币的习惯.于是他将火星上所有面值的硬币都收集起来了,一共有n种,每种只有一个:面值分别为a1,a ...