Swagger 简介

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

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

  为什么要使用 Swagger

  当下很多公司都采取前后端分离的开发模式,前端和后端的工作由不同的工程师完成。在这种开发模式下,维持一份及时更新且完整的 Rest API 文档将会极大的提高我们的工作效率。传统意义上的文档都是后端开发人员手动编写的,相信大家也都知道这种方式很难保证文档的及时性,这种文档久而久之也就会失去其参考意义,反而还会加大我们的沟通成本。而 Swagger 给我们提供了一个全新的维护 API 文档的方式,下面我们就来了解一下它的优点:

  1. 代码变,文档变。只需要少量的注解,Swagger 就可以根据代码自动生成 API 文档,很好的保证了文档的时效性。
  2. 跨语言性,支持 40 多种语言。
  3. Swagger UI 呈现出来的是一份可交互式的 API 文档,我们可以直接在文档页面尝试 API 的调用,省去了准备复杂的调用参数的过程。
  4. 还可以将文档规范导入相关的工具(例如 SoapUI), 这些工具将会为我们自动地创建自动化测试。

Swagger 使用

  准备项目

  1、准备一个Spring的Maven Web项目(test-swagger),参考:,pom.xml文件如下:

 <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/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.test</groupId>
<artifactId>test-swagger</artifactId>
<packaging>war</packaging>
<version>1.0-SNAPSHOT</version> <!-- 定义maven变量 -->
<properties>
<!-- spring -->
<spring.version>5.1.4.RELEASE</spring.version> <!-- log -->
<commons-logging.version>1.1.3</commons-logging.version> <!-- Servlet -->
<servlet.version>3.0.1</servlet.version>
<jsp-api.version>2.2</jsp-api.version> <!-- jstl -->
<jstl.version>1.2</jstl.version>
<standard.version>1.1.2</standard.version> <!-- Tool -->
<!-- jackson json包 -->
<jackson-databind.version>2.9.7</jackson-databind.version>
<jackson-core.version>2.9.7</jackson-core.version>
<jackson-annotations.version>2.9.7</jackson-annotations.version> <!-- test -->
<junit.version>3.8.1</junit.version> <!-- jdk -->
<jdk.version>1.8</jdk.version>
<maven.compiler.plugin.version>2.3.2</maven.compiler.plugin.version>
</properties> <dependencies> <dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>${spring.version}</version>
</dependency> <dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-beans</artifactId>
<version>${spring.version}</version>
</dependency> <dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>${spring.version}</version>
</dependency> <dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>${spring.version}</version>
</dependency> <dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-expression</artifactId>
<version>${spring.version}</version>
</dependency> <dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-web</artifactId>
<version>${spring.version}</version>
</dependency> <dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>${spring.version}</version>
</dependency> <dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-tx</artifactId>
<version>${spring.version}</version>
</dependency> <!-- Servlet -->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>${servlet.version}</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>javax.servlet.jsp</groupId>
<artifactId>jsp-api</artifactId>
<version>${jsp-api.version}</version>
<scope>provided</scope>
</dependency> <!-- jstl -->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>jstl</artifactId>
<version>${jstl.version}</version>
</dependency> <dependency>
<groupId>taglibs</groupId>
<artifactId>standard</artifactId>
<version>${standard.version}</version>
</dependency> <!-- jackson json包 -->
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>${jackson-databind.version}</version>
</dependency> <dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-core</artifactId>
<version>${jackson-core.version}</version>
</dependency> <dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-annotations</artifactId>
<version>${jackson-annotations.version}</version>
</dependency> <!-- swagger -->
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger2</artifactId>
<version>2.9.2</version>
</dependency> <dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger-ui</artifactId>
<version>2.9.2</version>
</dependency> <!-- test -->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>${junit.version}</version>
<scope>test</scope>
</dependency> </dependencies> <build>
<plugins>
<!-- define the project compile level -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>${maven.compiler.plugin.version}</version>
<configuration>
<source>${jdk.version}</source>
<target>${jdk.version}</target>
</configuration>
</plugin>
</plugins>
<finalName>test-swagger</finalName>
</build> </project>

pom.xml

 <?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:mvc="http://www.springframework.org/schema/mvc"
xmlns:context="http://www.springframework.org/schema/context" xmlns:tx="http://www.springframework.org/schema/tx" xmlns:util="http://www.springframework.org/schema/util"
xmlns:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-4.0.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsd
http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-4.0.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.0.xsd"> <!-- 注解注册 -->
<context:annotation-config /> <context:component-scan base-package="com.test" /> </beans>

spring-context.xml

 <?xml version="1.0" encoding="UTF-8" standalone="no"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:aop="http://www.springframework.org/schema/aop" xmlns:mvc="http://www.springframework.org/schema/mvc"
xmlns:p="http://www.springframework.org/schema/p" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsd
http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-4.0.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.0.xsd"> <!-- 自动扫描的包名 -->
<context:component-scan base-package="com.test.swagger" /> <!-- 默认的注解映射的支持 -->
<mvc:annotation-driven>
<mvc:message-converters>
<bean class="org.springframework.http.converter.StringHttpMessageConverter" />
<bean
class="org.springframework.http.converter.ResourceHttpMessageConverter" />
</mvc:message-converters>
</mvc:annotation-driven> <!-- 视图解释类,定义跳转的文件的前后缀 -->
<!-- <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="viewClass" value="org.springframework.web.servlet.view.JstlView"
/> <property name="prefix" value="/views/" /> <property name="suffix" value=".jsp"
/> <property name="requestContextAttribute" value="rc" /> </bean> -->
<bean id="viewResolver"
class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="viewClass"
value="org.springframework.web.servlet.view.JstlView" />
<property name="prefix" value="/view/" />
<property name="suffix" value=".jsp" />
</bean> <!-- 对静态资源文件的访问 方案一 (二选一) -->
<mvc:default-servlet-handler /> <!-- 对静态资源文件的访问 方案二 (二选一) -->
<!-- <mvc:resources mapping="/images/**" location="/images/" cache-period="31556926"/>
<mvc:resources mapping="/js/**" location="/js/" cache-period="31556926"/>
<mvc:resources mapping="/css/**" location="/css/" cache-period="31556926"/> -->
</beans>

spring-mvc.xml  

 <?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://java.sun.com/xml/ns/javaee"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
id="WebApp_ID" version="3.0">
<display-name>test-swagger</display-name> <!-- 指定Spring Bean的配置文件所在目录。默认配置在WEB-INF目录下 -->
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:spring-context.xml</param-value>
</context-param> <!-- Spring配置 -->
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener> <!-- Spring MVC配置 -->
<servlet>
<servlet-name>spring</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<!-- 可以自定义servlet.xml配置文件的位置和名称,默认为WEB-INF目录下,名称为[<servlet-name>]-servlet.xml,如spring-servlet.xml -->
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:spring-mvc.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet> <servlet-mapping>
<servlet-name>spring</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping> <!-- 中文过滤器 -->
<filter>
<filter-name>CharacterEncodingFilter</filter-name>
<filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
<init-param>
<param-name>encoding</param-name>
<param-value>UTF-8</param-value>
</init-param>
<init-param>
<param-name>forceEncoding</param-name>
<param-value>true</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>CharacterEncodingFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping> <welcome-file-list>
<welcome-file>index.jsp</welcome-file>
</welcome-file-list>
</web-app>

web.xml

  2、编写接口,UserController 提供用户的增、删、改、查四个接口

 package com.test.swagger.controller;

 import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController; import com.test.swagger.model.User; import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation; @Api(tags = "用户相关接口")
@RestController
@RequestMapping("/user")
public class UserController { @ApiOperation("新增用户接口")
@PostMapping("/add")
public boolean addUser(@RequestBody User user) {
return false;
} @GetMapping("/find/{id}")
public User findById(@PathVariable("id") int id) {
return new User();
} @PutMapping("/update")
public boolean update(@RequestBody User user) {
return true;
} @DeleteMapping("/delete/{id}")
public boolean delete(@PathVariable("id") int id) {
return true;
}
}

UserController.java

 package com.test.swagger.model;

 import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty; @ApiModel("用户实体")
public class User { @ApiModelProperty("用户 ID")
private Integer id; @ApiModelProperty("用户 名称")
private String name; public Integer getId() {
return id;
} public void setId(Integer id) {
this.id = id;
} public String getName() {
return name;
} public void setName(String name) {
this.name = name;
} }

User.java

  集成 Swagger2

  3、添加Swagger2依赖,如下:

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

  4、Swagger2配置,Springfox 提供了一个 Docket 对象,让我们可以灵活的配置 Swagger 的各项属性。下面我们新建一个SwaggerConfig.java 类,在SpringMvc扫描该类,就是将该类注入SpringMvc中,并增加如下内容:

 package com.test.swagger.conf;

 import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration; import springfox.documentation.builders.PathSelectors;
import springfox.documentation.builders.RequestHandlerSelectors;
import springfox.documentation.spi.DocumentationType;
import springfox.documentation.spring.web.plugins.Docket;
import springfox.documentation.swagger2.annotations.EnableSwagger2; @Configuration
@EnableSwagger2 // 作用是启用Swagger2相关功能。
public class SwaggerConfig { @Bean
public Docket api() {
return new Docket(DocumentationType.SWAGGER_2)
.select() // 选择那些路径和api会生成document
.apis(RequestHandlerSelectors.any()) // 对所有api进行监控
.paths(PathSelectors.any()) // 对所有路径进行监控
.build();
}
}

  5、验证集成了 Swagger2是否成功,发布项目,浏览器使用地址(http://ip:端口/项目名/v2/api-docs):http://localhost:8080/test-swagger/v2/api-docs,进行访问,发现返回的结果是一段 JSON 串,可读性非常差

  

  集成 Swagger UI

  Swagger2 为我们提供了可视化的交互界面 SwaggerUI

  6、添加SwaggerUI依赖

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

  7、验证集成了 SwaggerUI是否成功,发布项目,浏览器使用地址(http://ip:端口/项目名/swagger-ui.html):http://localhost:8080/test-swagger/swagger-ui.html

    

Swagger 注解配置

  文档相关描述配置

  1、通过在控制器类上增加@Api 注解,可以给控制器增加描述和标签信息。

    给 Controller 添加描述信息

 @Api(tags = "用户相关接口", description = "提供用户相关的 Rest API")
public class UserController

  2、通过在接口方法上增加 @ApiOperation 注解来展开对接口的描述,当然这个注解还可以指定很多内容

    给接口添加描述信息

 @ApiOperation("新增用户接口")
@PostMapping("/add")
public boolean addUser(@RequestBody User user) {
return false;
}

  3、实体描述,我们可以通过 @ApiModel 和 @ApiModelProperty 注解来对我们 API 中所涉及到的对象做描述。  

    给实体类添加描述信息

 @ApiModel("用户实体")
public class User {
@ApiModelProperty("用户 id")
  private int id;
}

  4、文档信息配置,Swagger 还支持设置一些文档的版本号、联系人邮箱、网站、版权、开源协议等等信息,但与上面几条不同的是这些信息不是通过注解配置,而是通过创建一个 ApiInfo 对象,并且使用 Docket.appInfo() 方法来设置,我们在 SwaggerConfig.java 类中新增如下内容即可  

    配置文档信息

 @Bean
public Docket api() {
return new Docket(DocumentationType.SWAGGER_2).select().apis(RequestHandlerSelectors.any())
.paths(PathSelectors.any()).build().apiInfo(apiInfo());
} private ApiInfo apiInfo() {
return new ApiInfo("Spring Web 项目集成 Swagger 实例文档", "欢迎大家访问。", "API V1.0",
"Terms of service", new Contact("OpenApi", "http://127.0.0.1", "123456@163.com"), "Apache",
"http://www.apache.org/", Collections.emptyList());
}

    通过以上配置,查看UI,如下:

    

  接口过滤

  有些时候我们并不是希望所有的 Rest API 都呈现在文档上,这种情况下 Swagger2 提供给我们了两种方式配置,一种是基于 @ApiIgnore 注解,另一种是在 Docket 上增加筛选。

  1、@ApiIgnore 注解。如果想在文档中屏蔽掉删除用户的接口(user/delete),那么只需要在删除用户的方法上加上 @ApiIgnore 即可。

 @ApiIgnore
public boolean delete(@PathVariable("id") int id)

  2、在 Docket 上增加筛选。Docket 类提供了 apis() 和 paths()两 个方法来帮助我们在不同级别上过滤接口:

  • apis():这种方式我们可以通过指定包名的方式,让 Swagger 只去某些包下面扫描。
  • paths():这种方式可以通过筛选 API 的 url 来进行过滤。
 .apis(RequestHandlerSelectors.basePackage("com.test.swagger.controller"))
.paths(Predicates.or(PathSelectors.ant("/user/add"),
PathSelectors.ant("/user/find/*")))

  自定义响应消息

  Swagger 允许我们通过 Docket 的 globalResponseMessage() 方法全局覆盖 HTTP 方法的响应消息,但是首先我们得通过 Docket 的 useDefaultResponseMessages 方法告诉 Swagger 不使用默认的 HTTP 响应消息,假设我们现在需要覆盖所有 GET 方法的 500 和 403 错误的响应消息,我们只需要在 SwaggerConfig.java 类中的 Docket Bean 下添加如下内容:

 @Bean
public Docket api() {
List<ResponseMessage> responseMessageList = new ArrayList<>();
responseMessageList.add( new ResponseMessageBuilder().code(500).message("服务器发生异常").responseModel(new ModelRef("Error")).build());
responseMessageList.add( new ResponseMessageBuilder().code(403).message("资源不可用").build()); return new Docket(DocumentationType.SWAGGER_2).select().apis(RequestHandlerSelectors.any())
.paths(PathSelectors.any()).build().apiInfo(apiInfo()).useDefaultResponseMessages(false)
.globalResponseMessage(RequestMethod.GET,responseMessageList);
}

Swagger 接口调用

  如下图所示,点击接口展开后页面右上角的 Try it out 按钮后,页面会变成如图所示:

  接口详情界面

    

  
  SwaggerUI 会给我们自动填充请求参数的数据结构,我们需要做的只是点击 Execute 即可发起调用

  接口调用界面

    

  Model

  如下图所示,SwaggerUI 会通过我们在实体上使用的 @ApiModel 注解以及@ApiModelProperty 注解来自动补充实体以及其属性的描述和备注。

  实体界面

    

  

最新文章

  1. C#读取XML文件
  2. java7-3 继承
  3. [转载]破解TexturePacker加密资源
  4. Thread+Handler 线程 消息循环(转载)
  5. php生成二维码
  6. tab选项卡-jQuery
  7. SpringMVC原理+流程图
  8. 柯南君:看大数据时代下的IT架构(8)消息队列之RabbitMQ--案例(topic起航)
  9. JavaScript提高:005:ASP.NET使用easyUI TABS标签显示问题
  10. 看AngularJS
  11. Oracle EBS中分类账和法人实体 的关系(有sql语句实例)
  12. [转]使用openssl库实现RSA、AES数据加密
  13. k倍区间
  14. Spring框架第二天
  15. Adobe reader multiple languages pack
  16. vue之路由嵌套,子路由
  17. 服装盘点机PDA在服装行业颜色尺码仓库条码高效管理应用
  18. 在Linux CentOS 6.6上安装RedisLive
  19. android http json请求3种不同写法
  20. linux 虚拟机 磁盘空间压缩

热门文章

  1. influxDB应用及TICK stack
  2. javascript数据结构与算法——栈
  3. 代码优化 - 求数组中的第 K 个最大元素
  4. 解决 Vue 刷新页面后 store 数据丢失的问题
  5. 项目Beta冲刺——凡事预则立
  6. danci2
  7. web自动化测试-模块驱动测试实例和数据驱动测试实例
  8. 我永远讨厌gch文件
  9. BZOJ 3451: Tyvj1953 Normal 点分治+FFT
  10. BZOJ 2006: [NOI2010]超级钢琴 ST表+堆