转自   Vojtech Ruzicka的编程博客

(一)Swagger和SpringFox

记录REST API非常重要。它是一个公共接口,其他模块,应用程序或开发人员可以使用它。即使你没有公开曝光它,它仍然很重要。后端和前端代码通常由不同的开发人员处理。创建API的人通常不是消费它的人。因此,拥有适当记录的界面以避免混淆并使其始终保持最新是至关重要的。

最受欢迎的API文档规范之一是OpenApi,以前称为Swagger。它允许您使用JSON或YAML元数据描述API的属性。它还提供了一个Web UI,它可以将元数据转换为一个很好的HTML文档。此外,通过该UI,您不仅可以浏览有关API端点的信息,还可以将UI用作REST客户端 - 您可以调用任何端点,指定要发送的数据并检查响应。它非常方便。

然而,手动编写此类文档并在代码更改时保持更新是不现实的。这就是SpringFox发挥作用的地方。它是Spring Framework的Swagger集成。它可以自动检查您的类,检测控制器,它们的方法,它们使用的模型类以及它们映射到的URL。没有任何手写文档,只需检查应用程序中的类,它就可以生成大量有关API的信息。多么酷啊?最重要的是,每当您进行更改时,它们都会反映在文档中。

(二)开始项目

首先,你需要一个带有一些Rest Controller的Spring Boot应用程序,我在这里准备了一个简单的。

在本文中,我使用了SpringFox 2.9.2和Spring Boot 1.5.10.RELEASE。它使用Swagger规范的第2版。版本3已经发布,但尚未(截至2014年2月)SpringFox支持。支持应在下一版本中提供

使用本博文中描述的所有功能构建的最终项目的源代码可在GitHub上获得

(三)添加依赖项

要在项目中使用SpringFox,您需要先将其添加为依赖项。如果您使用的是Maven,则可以使用以下内容(您可以检查是否有更新的版本)。

<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger2</artifactId>
<version>2.9.2</version>
</dependency>

或者如果您使用的是Gradle:

compile "io.springfox:springfox-swagger2:2.9.2"

(四)基本配置

添加依赖项后,您需要提供一些基本的Spring配置。虽然您可以在技术上使用现有配置文件之一,但最好为其配置单独的文件。您需要提供的第一件事是@ EnableSwagger2注释。然后你需要提供一个Docket bean,它是用于配置SpringFox的主bean。

@Configuration
@EnableSwagger2
public class SpringFoxConfig {
@Bean
public Docket apiDocket() {
return new Docket(DocumentationType.SWAGGER_2)
.select()
.apis(RequestHandlerSelectors.any())
.paths(PathSelectors.any())
.build();
}
}

当然,您可以提供更多配置设置,我们稍后会看到,但这是一个简约配置,它执行以下操作:

  • @ EnableSwagger2支持Swagger 2的SpringFox支持。
  • DocumentationType.SWAGGER_2告诉Docket bean我们正在使用Swagger规范的版本2。
  • select()创建一个构建器,用于定义哪些控制器及其生成的文档中应包含哪些方法。
  • apis()定义要包含的类(控制器和模型类)。这里我们包括所有这些,但您可以通过基础包,类注释等来限制它们。
  • paths()允许您根据路径映射定义应包含哪个控制器的方法。我们现在包括所有这些,但您可以使用正则表达式等限制它。

(五)添加UI

如果您现在部署应用程序,则已经生成了描述API的swagger元数据!你可以看看:

http://localhost:8080/v2/api-docs

事实证明它只是一个很大的JSON,而不是人类可读的。但你已经可以验证它是否有效。只需转到Swagger在线编辑器并将JSON粘贴到那里。将生成的JSON粘贴到左侧面板,瞧!您现在可以将生成的文档视为HTML页面。不错,不是吗?将这些文档作为应用程序的一部分直接使用会更好。幸运的是,实现这一点非常容易。显示基于JSON输入的HTML文档的GUI称为swagger-ui。要启用它是一个Spring Boot应用程序,您只需要添加此依赖项:

//MAVEN
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger-ui</artifactId>
<version>2.9.2</version>
</dependency> //GRADLE
compile "io.springfox:springfox-swagger-ui:2.9.2"

该文档将在此处自动提供:

http://localhost:8080/swagger-ui.html

(六)添加ApiInfo

默认情况下,我们文档的标题部分看起来非常通用:

现在是时候做点什么了。我们可以通过简单的配置更改来更改那里的所有信息。在SpringFoxConfiguration文件中,我们需要添加ApiInfo对象,该对象提供有关API的一般信息,例如标题,版本,联系人或许可信息。

@Bean
public Docket apiDocket() {
return new Docket(DocumentationType.SWAGGER_2)
.select()
.apis(RequestHandlerSelectors.any())
.paths(PathSelectors.any())
.build()
.apiInfo(getApiInfo());
} private ApiInfo getApiInfo() {
return new ApiInfo(
"TITLE",
"DESCIPRION",
"VERSION",
"TERMS OF SERVICE URL",
new Contact("NAME","URL","EMAIL"),
"LICENSE",
"LICENSE URL",
Collections.emptyList()
);
}

现在我们的文档标题应该看起来更好:

(七)缩小已处理的API

到现在为止还挺好。但是当你仔细看看生成的文档时,你会发现除了我们使用的模型和控制器类之外,还有一些特定于Spring的类,如Controllers部分中的BasicErrorController以及ViewModelAndView下的型号部分。

有时,缩小类,SpringFox会将其检测为文档生成源。Controller和Model类。您可以在Docket配置中轻松配置它。还记得像我们使用.apis(RequestHandlerSelectors.any()来包含所有类吗?让我们将它缩小到我们的基础包:

@Bean
public Docket apiDocket() {
return new Docket(DocumentationType.SWAGGER_2)
.select()
.apis(RequestHandlerSelectors.basePackage("com.vojtechruzicka"))
.paths(PathSelectors.any())
.build()
.apiInfo(getApiInfo());
}

当您想要指定应包含哪些类时,这非常有用。有时您还需要只包含特定的URL路径。您可能正在使用API​​的多个版本以实现向后兼容,但不希望包含历史版本。也许API的某些部分是内部的,不应该是公共文档的一部分。无论哪种方式,也可以在Docket中配置基于URL匹配的这种包含。记住.paths(PathSelectors.any())?您可以将其限制为某些正则表达式或Ant样式的路径模式,而不是匹配所有路径的任何路径

@Bean
public Docket apiDocket() {
return new Docket(DocumentationType.SWAGGER_2)
.select()
.apis(RequestHandlerSelectors.basePackage("com.vojtechruzicka"))
.paths(PathSelectors.ant("/v2/**"))
.build()
.apiInfo(getApiInfo());
}

如果内置选项对您来说还不够,您可以随时为apis()paths()提供自己的谓词。忽略某些类或方法的另一种方法是使用@ApiIgnore注释它们。

(八)使用JSR-303注解

JSR 303:Bean Validation  允许您注释Java类的字段以声明约束和验证规则。您可以使用以下规则注释单个字段: - 不能为空,最小值,最大值,正则表达式匹配等。

public class Person {
@NotNull
private int id; @NotBlank
@Size(min = 1, max = 20)
private String firstName; @NotBlank
@Pattern(regexp ="[SOME REGULAR EXPRESSION]")
private String lastName; @Min(0)
@Max(100)
private int age; //... Constructor, getters, setters, ...
}

这是一种已经广泛使用的常见做法。好消息是,SpringFox可以根据这些注释生成Swagger文档,因此您可以利用项目中已有的内容而无需手动编写所有约束!它非常有用,因为您的API的消费者知道他们应该为您的API提供的值的限制以及期望的值。如果没有包含这样的注释,我们的人员模型的生成文档看起来很简单,除了字段名称及其数据类型之外什么也没有。

使用来自JSR-303注释的数据,它看起来会更好:

不幸的是,基于JSR-303的文档无法开箱即用,您需要一个额外的依赖:

//MAVEN
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-bean-validators</artifactId>
<version>2.9.2</version>
</dependency> //GRADLE
compile "io.springfox:springfox-bean-validators:2.9.2"

并且您需要在swagger配置类之上导入BeanValidatorPluginsConfiguration配置文件:

@Configuration
@EnableSwagger2
@Import(BeanValidatorPluginsConfiguration.class)
public class SpringFoxConfig {
...
}

(九)将Swagger Core注释添加到模型类中

使用JSR-303的优点是,如果您已经使用它们,您可以毫不费力地获得额外的文档信息,而无需更改任何代码。问题是目前,SpringFox不显示注释中指定的验证消息。此外,您可能需要记录一些更复杂的约束。在这种情况下,您可以使用Swagger Core注释,它允许您指定其他信息,例如描述。用这些注释注释的Person类可以看起来像这样。

@ApiModel(description = "Class representing a person tracked by the application.")
public class Person {
@ApiModelProperty(notes = "Unique identifier of the person. No two persons can have the same id.", example = "", required = true, position = 0)
private int id;
@ApiModelProperty(notes = "First name of the person.", example = "John", required = true, position = 1)
private String firstName;
@ApiModelProperty(notes = "Last name of the person.", example = "Doe", required = true, position = 2)
private String lastName;
@ApiModelProperty(notes = "Age of the person. Non-negative integer", example = "", position = 3)
private int age; // … Constructor, getters, setters, ...
}

在类级别,您使用@ApiModel注释并在字段级别@ApiModelProperty。当然,您可以与JSR-303注释混合搭配。 @ApiModelProperty的示例对于提供示例值非常有用,这不仅适用于用户的指导,而且还可以在使用Swagger UI作为REST客户端来测试服务时预填充请求有效负载。Position属性很方便指定属性在文档中显示的顺序。首先提供重要或必需的属性或属于一起的组属性是有用的。否则,属性将按字母顺序列出。

(十)将Swagger Core注释添加到控制器类

与使用Swagger核心注释注释模型类以提供其他元数据相同,您可以注释控制器及其方法和方法参数。

  • @Api描述了整个控制器
  • @ApiOperation用于方法级别的描述
  • @ApiParam用于方法参数
@RestController
@RequestMapping("/v2/persons/")
@Api(description = "Set of endpoints for Creating, Retrieving, Updating and Deleting of Persons.")
public class PersonController { private PersonService personService; @RequestMapping(method = RequestMethod.GET, produces = "application/json")
@ApiOperation("Returns list of all Persons in the system.")
public List getAllPersons() {
return personService.getAllPersons();
} @RequestMapping(method = RequestMethod.GET, path = "/{id}", produces = "application/json")
@ApiOperation("Returns a specific person by their identifier. 404 if does not exist.")
public Person getPersonById(@ApiParam("Id of the person to be obtained. Cannot be empty.")
@PathVariable int id) {
return personService.getPersonById(id);
} @RequestMapping(method = RequestMethod.DELETE, path = "/{id}")
@ApiOperation("Deletes a person from the system. 404 if the person's identifier is not found.")
public void deletePerson(@ApiParam("Id of the person to be deleted. Cannot be empty.")
@PathVariable int id) {
personService.deletePerson(id);
} @RequestMapping(method = RequestMethod.POST, produces = "application/json")
@ApiOperation("Creates a new person.")
public Person createPerson(@ApiParam("Person information for a new person to be created.")
@RequestBody Person person) {
return personService.createPerson(person);
} @Autowired
public void setPersonService(PersonService personService) {
this.personService = personService;
}
}

现在您的文档还应包含所提供的描述:

请注意,我们的控制器和域类现在受到Swagger特定注释的困扰。可读性受到很大影响,因为重要的信息在大量的漏洞中丢失了。更糟糕的是 - 当您更改代码时,以这种方式编写的文档不会更新,您需要记住手动更改消息。这会增加您的文档不同步的风险,因此不值得信任。最好包括一些不明显的基本信息,而这些信息尚未被自动生成的信息很好地涵盖。具有参数的描述性名称以及JSR-303注释通常可以记录大部分所需信息。

(十一)从属性文件加载描述

直接在注释中提供描述并不是很优雅。它可能占用大量空间,污染您的代码。你不能真正支持多种语言。如果要修复拼写错误或对文档进行一些更改,则需要重新构建并重新部署整个应用程序。根据环境,您不能拥有不同的值。不是很灵活。幸运的是,Spring提供了Property占位符的概念。简而言之,它允许您提供占位符$ {placeholder}而不是硬编码值。然后在.properties文件中定义占位符的值。Spring从属性加载数据并注入它而不是占位符。很酷的是,您可以为每种语言提供多个属性文件。您可以在不同的环境中提供不同的属性文件。

SpringFox在一些注释中支持这种机制。这是一种很好的方法,可以将文档与代码分离,并具有更大的灵活性。不幸的是,目前只支持一些注释。因此,例如在模型中,它们在方法级别(@ApiModelProperty)上支持它,但在类级别(@ApiModel)上不支持它。

要完成这项工作,您需要:

  1. 创建属性文件,例如swagger.properties
  2. 输入您想要的消息作为键值对,其中键将用作占位符 - 例如person.id =此人的唯一标识符
  3. 而不是注释文本插入占位符 - 例如$ {person.id}
  4. 在类级别注册配置中的属性文件 - 例如。 @PropertySource( “类路径:swagger.properties”)

结论

SpringFox是一个有用的工具,它可以根据您的Spring控制器和模型类自动生成Swagger文档。它还可以识别JSR-303注释,因此您还要记录模型类的所有约束。它还可以使用核心的swagger类,例如@ApiModelProperty。但要小心,因为这会使你的代码充满了大量特定的注释。只有在SpringFox无法推断信息本身时才使用它们总是更好。仅在需要添加某些描述时才使用它们,其中类,属性和方法名称不能自我解释。再说一遍,你的API可能是一个红色标志,说明你的API是神秘的还是太复杂了。如果您保留由SpringFox自动生成的大部分文档,您可以确保它始终是最新的。除此以外,在代码中进行更改时,您需要非常小心地更新Core Swagger注释。如果您的文档和代码不匹配,用户将失去对您的API文档的信任,并且此类文档几乎无用。

------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

声明: 本文转自      Vojtech Ruzicka的编程博客

Swagger 教程的更多相关文章

  1. Asp.Net MVC Web API 中Swagger教程,使用Swagger创建Web API帮助文件

    什么是Swagger? Swagger 是一个规范和完整的框架,用于生成.描述.调用和可视化 RESTful 风格的 Web 服务.总体目标是使客户端和文件系统作为服务器以同样的速度来更新.文件的方法 ...

  2. springboot swagger教程😀

    传送门开启:https://www.ibm.com/developerworks/cn/java/j-using-swagger-in-a-spring-boot-project/index.html

  3. Swagger快速入门教程笔记

    现在市面上大多数公司都摒弃了传统 jsp 开发,采用前后端分离式的开发规则,前端使用 Vue,Angular,React 等等完成页面,后端省掉了视图跳转的过程,直接书写接口返回 json 数据供前端 ...

  4. Swagger入门教程

    [译]5.41 Swagger tutorial 单击此处查看原文 更多概念参见:Implementing Swagger with your API docs 关于 Swagger Swagger能 ...

  5. Spring Boot 2.x基础教程:Swagger接口分类与各元素排序问题详解

    之前通过Spring Boot 2.x基础教程:使用Swagger2构建强大的API文档一文,我们学习了如何使用Swagger为Spring Boot项目自动生成API文档,有不少用户留言问了关于文档 ...

  6. Spring Boot 2.x基础教程:Swagger静态文档的生成

    前言 通过之前的两篇关于Swagger入门以及具体使用细节的介绍之后,我们已经能够轻松地为Spring MVC的Web项目自动构建出API文档了.如果您还不熟悉这块,可以先阅读: Spring Boo ...

  7. Swagger入门教程(转)

    [译]5.41 Swagger tutorial 单击此处查看原文 更多概念参见:Implementing Swagger with your API docs 关于 Swagger Swagger能 ...

  8. springboot2.x基础教程:Swagger详解给你的接口加上文档说明

    相信无论是前端还是后端开发,都或多或少地被接口文档折磨过.前端经常抱怨后端给的接口文档与实际情况不一致.后端又觉得编写及维护接口文档会耗费不少精力,经常来不及更新.其实无论是前端调用后端,还是后端调用 ...

  9. 《Asp.Net Core3 + Vue3入坑教程》-Net Core项目搭建与Swagger配置步骤

    简介 <Asp.Net Core3 + Vue3入坑教程> 此教程仅适合新手入门或者前后端分离尝试者.可以根据图文一步一步进操作编码也可以选择直接查看源码.每一篇文章都有对应的源码 教程后 ...

随机推荐

  1. Laravel5.5 综合使用

    使用 Laravel5.5 开发一个自动交割的项目,把使用到的开源扩展包及特性整理起来,以供后续使用. 一.安装IDE提示工具 Laravel IDE Helper 是一个极其好用的代码提示及补全工具 ...

  2. Python的import module与form module import的区别

    import moduleName 如果要使用moduleName模块中的方法时,是moduleName.method(点方法), 比如moduleName中有个方法是set,则使用的是moduleN ...

  3. ganglia371 on suse11sp3

    参考https://my.oschina.net/duangr/blog/181585 1.确认依赖包是否已安装 确认命令:rpm -qa  如下为适合suse11sp3的依赖包版本 apr: lib ...

  4. 关于zookeeper和zkfc的一些测试

    1.停掉zookeeper集群 ****进程影响****** zkfc:报错无法连接zookeeper.ClientCnxn java.net.connectexception:拒绝连接,但不会shu ...

  5. poj 3253 Fence Repair(priority_queue)

    Fence Repair Time Limit: 2000MS   Memory Limit: 65536K Total Submissions: 40465   Accepted: 13229 De ...

  6. HDU 1540 区间合并线段树

    题目大意: 就是给定一堆位置,进行删除还原,最后找到 t 位置上的最大连续位置 #include <cstdio> #include <cstring> #include &l ...

  7. HDU 3308 (线段树区间合并)

    http://acm.hdu.edu.cn/showproblem.php?pid=3308 题意: 两个操作  : 1 修改 单点  a 处的值. 2 求出 区间[a,b]内的最长上升子序列. 做法 ...

  8. 生成随机数验证码的工具类(from韩顺平)

    生成随机数验证码的工具类 package com.cx; //生成随机数的图片 import java.awt.Color; import java.awt.Font; import java.awt ...

  9. nyoj_68_三点顺序_201404152013

    三点顺序 时间限制:1000 ms  |  内存限制:65535 KB 难度:3   描述 现在给你不共线的三个点A,B,C的坐标,它们一定能组成一个三角形,现在让你判断A,B,C是顺时针给出的还是逆 ...

  10. Ubuntu 16.04监控网络带宽软件

    1.系统监控器已经自带了默认的监控功能,包括CPU.内存.带宽.进程等,但带宽的一些详情不能显示出来. 2.使用top命令进行监控进程 sudo top 3.安装Indicator-sysmonito ...