【Java】Swagger快速入门
Swagger 简介
Swagger 是一套基于 OpenAPI 规范构建的开源工具,可以帮助我们设计、构建、记录以及使用 Rest API。Swagger 主要包含了以下三个部分:
- Swagger Editor:基于浏览器的编辑器,我们可以使用它编写我们 OpenAPI 规范。
- Swagger UI:它会将我们编写的 OpenAPI 规范呈现为交互式的 API 文档,后文我将使用浏览器来查看并且操作我们的 Rest API。
- Swagger Codegen:它可以通过为 OpenAPI(以前称为 Swagger)规范定义的任何 API 生成服务器存根和客户端 SDK 来简化构建过程。
为什么要使用 Swagger
当下很多公司都采取前后端分离的开发模式,前端和后端的工作由不同的工程师完成。在这种开发模式下,维持一份及时更新且完整的 Rest API 文档将会极大的提高我们的工作效率。传统意义上的文档都是后端开发人员手动编写的,相信大家也都知道这种方式很难保证文档的及时性,这种文档久而久之也就会失去其参考意义,反而还会加大我们的沟通成本。而 Swagger 给我们提供了一个全新的维护 API 文档的方式,下面我们就来了解一下它的优点:
- 代码变,文档变。只需要少量的注解,Swagger 就可以根据代码自动生成 API 文档,很好的保证了文档的时效性。
- 跨语言性,支持 40 多种语言。
- Swagger UI 呈现出来的是一份可交互式的 API 文档,我们可以直接在文档页面尝试 API 的调用,省去了准备复杂的调用参数的过程。
- 还可以将文档规范导入相关的工具(例如 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
注解来自动补充实体以及其属性的描述和备注。
实体界面
最新文章
- C#读取XML文件
- java7-3 继承
- [转载]破解TexturePacker加密资源
- Thread+Handler 线程 消息循环(转载)
- php生成二维码
- tab选项卡-jQuery
- SpringMVC原理+流程图
- 柯南君:看大数据时代下的IT架构(8)消息队列之RabbitMQ--案例(topic起航)
- JavaScript提高:005:ASP.NET使用easyUI TABS标签显示问题
- 看AngularJS
- Oracle EBS中分类账和法人实体 的关系(有sql语句实例)
- [转]使用openssl库实现RSA、AES数据加密
- k倍区间
- Spring框架第二天
- Adobe reader multiple languages pack
- vue之路由嵌套,子路由
- 服装盘点机PDA在服装行业颜色尺码仓库条码高效管理应用
- 在Linux CentOS 6.6上安装RedisLive
- android http json请求3种不同写法
- linux 虚拟机 磁盘空间压缩