Swagger
https://blog.csdn.net/u013735734/article/details/103249989
前言
目前来说,在 Java 领域使用 Springboot 构建微服务是比较流行的,在构建微服务时,我们大多数会选择暴漏一个 REST API 以供调用。又或者公司采用前后端分离的开发模式,让前端和后端的工作由完全不同的工程师进行开发完成。不管是微服务还是这种前后端分离开发,维持一份完整的及时更新的 REST API 文档,会极大的提高我们的工作效率。而传统的文档更新方式(如手动编写),很难保证文档的及时性,经常会年久失修,失去应有的意义。因此选择一种新的 API 文档维护方式很有必要,这也是这篇文章要介绍的内容。
OpenAPI 规范介绍
OpenAPI Specification 简称 OAS,中文也称 OpenAPI 描述规范,使用 OpenAPI 文件可以描述整个 API,它制定了一套的适合通用的与语言无关的 REST API 描述规范,如 API 路径规范、请求方法规范、请求参数规范、返回格式规范等各种相关信息,使人类和计算机都可以不需要访问源代码就可以理解和使用服务的功能。
下面是 OpenAPI 规范中建议的 API 设计规范,基本路径设计规范。
对于传参的设计也有规范,可以像下面这样:
路径参数, 例如 /users/{id}
查询参数, 例如 /users?role=未读代码
header 参数, 例如 X-MyHeader: Value
cookie 参数, 例如 Cookie: debug=0; csrftoken=BUSe35dohU3O1MZvDCU
OpenAPI 规范的东西远远不止这些,目前 OpenAPI 规范最新版本是 3.0.2,如果你想了解更多的 OpenAPI 规范,可以访问下面的链接。
OpenAPI Specification (https://github.com/OAI/OpenAPI-Specification/blob/master/versions/3.0.2.md)
Swagger 介绍
很多人都以为 Swagger 只是一个接口文档生成框架,其实并不是。 Swagger 是一个围绕着 OpenAPI Specification(OAS,中文也称 OpenAPI规范)构建的一组开源工具。可以帮助你从 API 的设计到 API 文档的输出再到 API 的测试,直至最后的 API 部署等整个 API 的开发周期提供相应的解决方案,是一个庞大的项目。 Swagger 不仅免费,而且开源,不管你是企业用户还是个人玩家,都可以使用 Swagger 提供的方案构建令人惊艳的 REST API。
Swagger 有几个主要的产品。
Swagger Editor – 一个基于浏览器的 Open API 规范编辑器。
Swagger UI – 一个将 OpenAPI 规范呈现为可交互在线文档的工具。
Swagger Codegen – 一个根据 OpenAPI 生成调用代码的工具。
如果你想了解更多信息,可以访问 Swagger 官方网站 https://swagger.io。
- Springfox 介绍
源于 Java 中 Spring 框架的流行,让一个叫做 Marrty Pitt 的老外有了为 SpringMVC 添加接口描述的想法,因此他创建了一个遵守 OpenAPI 规范(OAS)的项目,取名为 swagger-springmvc,这个项目可以让 Spring 项目自动生成 JSON 格式的 OpenAPI 文档。这个框架也仿照了 Spring 项目的开发习惯,使用注解来进行信息配置。
后来这个项目发展成为 Springfox,再后来扩展出 springfox-swagger2 ,为了让 JSON 格式的 API 文档更好的呈现,又出现了 springfox-swagger-ui 用来展示和测试生成的 OpenAPI 。这里的 springfox-swagger-ui 其实就是上面介绍的 Swagger-ui,只是它被通过 webjar 的方式打包到 jar 包内,并通过 maven 的方式引入进来。
上面提到了 Springfox-swagger2 也是通过注解进行信息配置的,那么是怎么使用的呢?下面列举常用的一些注解,这些注解在下面的 Springboot 整合 Swagger 中会用到。
更多的 Springfox 介绍,可以访问 Springfox 官方网站。
Springfox Reference Documentation (http://springfox.github.io)
Springboot 整合 Swagger
就目前来说 ,Springboot 框架是非常流行的微服务框架,在微服务框架下,很多时候我们都是直接提供 REST API 的。REST API 如果没有文档的话,使用者就很头疼了。不过不用担心,上面说了有一位叫 Marrty Pitt 的老外已经创建了一个发展成为 Springfox 的项目,可以方便的提供 JSON 格式的 OpenAPI 规范和文档支持。且扩展出了 springfox-swagger-ui 用于页面的展示。
需要注意的是,这里使用的所谓的 Swagger 其实和真正的 Swagger 并不是一个东西,这里使用的是 Springfox 提供的 Swagger 实现。它们都是基于 OpenAPI 规范进行 API 构建。所以也都可以 Swagger-ui 进行 API 的页面呈现。
创建项目
导入依赖
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-boot-starter</artifactId>
<version>3.0.0</version>
</dependency>
添加配置类
import io.swagger.annotations.ApiOperation;
import org.springframework.boot.SpringBootConfiguration;
import org.springframework.context.annotation.Bean;
import springfox.documentation.builders.ApiInfoBuilder;
import springfox.documentation.builders.PathSelectors;
import springfox.documentation.builders.RequestHandlerSelectors;
import springfox.documentation.oas.annotations.EnableOpenApi;
import springfox.documentation.service.ApiInfo;
import springfox.documentation.service.Contact;
import springfox.documentation.spi.DocumentationType;
import springfox.documentation.spring.web.plugins.Docket;
@SpringBootConfiguration
@EnableOpenApi
public class Swagger3Config {
/**
* ture 启用Swagger3.0, false 禁用(生产环境要禁用)
*/
Boolean swaggerEnabled=true;
@Bean
public Docket createRestApi(){
return new Docket(DocumentationType.OAS_30)
.apiInfo(apiInfo())
// 是否开启
.enable(swaggerEnabled)
.select()
// 扫描的路径使用@Api的controller .apis(RequestHandlerSelectors.withMethodAnnotation(ApiOperation.class))
// 指定路径处理PathSelectors.any()代表所有的路径
.paths(PathSelectors.any())
.build();
}
private ApiInfo apiInfo(){
return new ApiInfoBuilder()
.title("东软人力资源管理系统接口文档")
.description("使用springboot实现后端内容")
//作者信息
.contact(new Contact("鲍晖","http://www.neusoft.com/", "pcbhyy@163.com"))
.version("1.0")
.build();
}
}
注解类和方法
package com.neu.springbootdemo1.controller;
import com.neu.springbootdemo1.entity.Dept;
import com.neu.springbootdemo1.entity.Result;
import com.neu.springbootdemo1.service.DeptService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*;
import javax.annotation.Resource;
import java.util.List;
@Api(tags = "部门管理")
@RestController
@RequestMapping("dept")
public class DeptController {
@Resource
private DeptService deptService;
@ApiOperation("查询所有部门")
@GetMapping("getAll")
public Result getAll(){
return new Result(deptService.getAll());
}
@ApiOperation("根据部门编号查询部门")
@GetMapping("{deptno}")
public Dept getById(@PathVariable("deptno") long deptno){
return deptService.selectByPrimaryKey(deptno);
}
@ApiOperation("添加部门")
@PostMapping
public Result insert(@RequestBody Dept dept){
return new Result(deptService.insert(dept));
}
@ApiOperation("修改部门")
@PutMapping
public Result update(@RequestBody Dept dept){
return new Result(deptService.updateByPrimaryKey(dept));
}
@ApiOperation("修改部门部分值")
@PatchMapping
public int updateByPrimaryKeySelective(@RequestBody Dept dept){
return deptService.updateByPrimaryKeySelective(dept);
}
@ApiOperation("根据部门编号删除部门")
@DeleteMapping("{deptno}")
public Result delete(@PathVariable("deptno") long deptno){
return new Result(deptService.deleteByPrimaryKey(deptno));
}
}
运行测试
http://localhost:8086/swagger-ui/index.html
配置
新建一个maven项目
配置pom.xml
<?xml version="1.0" encoding="UTF-8"?> <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/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>org.example</groupId> <artifactId>swagger_demo</artifactId> <packaging>war</packaging> <version>1.0-SNAPSHOT</version> <build> <plugins> <!-- 资源文件拷贝插件 --> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-resources-plugin</artifactId> <version>2.7</version> <configuration> <encoding>UTF-8</encoding> </configuration> </plugin> <!-- java编译插件 --> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-compiler-plugin</artifactId> <version>3.2</version> <configuration> <source>1.8</source> <target>1.8</target> <encoding>UTF-8</encoding> </configuration> </plugin> <plugin> <groupId>org.apache.tomcat.maven</groupId> <artifactId>tomcat7-maven-plugin</artifactId> <version>2.2</version> <configuration> <!-- 部署路径,如:/e3mall,表明部署到/e3mall路径下 --> <path>/</path> <!-- 端口号 --> <port>8089</port> <uriEncoding>utf-8</uriEncoding> </configuration> </plugin> </plugins> </build> <dependencies> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-webmvc</artifactId> <version>4.0.9.RELEASE</version> </dependency> <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> <!-- https://mvnrepository.com/artifact/com.fasterxml.jackson.core/jackson-databind --> <dependency> <groupId>com.fasterxml.jackson.core</groupId> <artifactId>jackson-databind</artifactId> <version>2.9.5</version> </dependency> <dependency> <groupId>com.github.xiaoymin</groupId> <artifactId>swagger-bootstrap-ui</artifactId> <version>1.6</version> </dependency> </dependencies> </project>
配置 resources 目录下的 spring-mvc.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" xsi:schemaLocation="http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-4.3.xsd http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.3.xsd"> <!-- 启用mvc注解驱动 --> <mvc:annotation-driven></mvc:annotation-driven> <!-- 组件扫描 --> <context:component-scan base-package="com.neu.controller"></context:component-scan> <!-- 配置视图解析器,把逻辑视图名转换为物理视图名 --> <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver"> <property name="prefix" value="/WEB-INF/jsp/"></property> <property name="suffix" value=".jsp"></property> </bean> <bean class="com.neu.SwaggerConfig" /> <mvc:resources mapping="swagger-ui.html" location="classpath:/META-INF/resources/" /> <mvc:resources mapping="/webjars/**" location="classpath:/META-INF/resources/webjars/" /> </beans>
配置 web.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" xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd" version="3.0"> <servlet> <servlet-name>DispatcherServlet</servlet-name> <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> <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>DispatcherServlet</servlet-name> <url-pattern>*.do</url-pattern> <url-pattern>/swagger/*</url-pattern> <url-pattern>/api-docs</url-pattern> </servlet-mapping> <servlet-mapping> <servlet-name>DispatcherServlet</servlet-name> <url-pattern>*.action</url-pattern> </servlet-mapping> </web-app>
添加 配置类 SwaggerConfig
package com.neu; import io.swagger.annotations.Api; import io.swagger.annotations.ApiOperation; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.web.servlet.config.annotation.EnableWebMvc; import springfox.documentation.builders.ApiInfoBuilder; import springfox.documentation.builders.RequestHandlerSelectors; import springfox.documentation.service.ApiInfo; import springfox.documentation.spi.DocumentationType; import springfox.documentation.spring.web.plugins.Docket; import springfox.documentation.swagger2.annotations.EnableSwagger2; @Configuration @EnableWebMvc @EnableSwagger2 public class SwaggerConfig{ @Bean public Docket api() { return new Docket(DocumentationType.SWAGGER_2) .select() .apis(RequestHandlerSelectors.withClassAnnotation(Api.class)) .apis(RequestHandlerSelectors.withMethodAnnotation(ApiOperation.class)) .build() .apiInfo(apiInfo()); } private ApiInfo apiInfo() { return new ApiInfoBuilder() .title("监管平台-国际版API") .description("http不对外开放接口") .version("1.0.0") .termsOfServiceUrl("http://xxx.xxx.com") .license("假装这里有license") .licenseUrl("http://xxx.xxx.com") .build(); } }
编写控制器(没有与接口内容对应匹配)
package com.neu.controller; import io.swagger.annotations.Api; import io.swagger.annotations.ApiImplicitParam; import io.swagger.annotations.ApiOperation; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.bind.annotation.RestController; @Api(value = "User控制器") @RestController public class HelloController { @ApiOperation(value="创建用户", notes="根据User对象创建用户") @ApiImplicitParam(name = "user", value = "用户详细实体user", required = true, dataType = "User") @RequestMapping(value="hi",method = {RequestMethod.GET}) public String hi(){ return "hi"; } }
测试:
http://localhost:8089/swagger/swagger-ui.html 或 http://localhost:8089/doc.html
API
注解 属性 备注
@Api
用于类上,说明该类的作用。可以标记一个Controller类做为swagger 文档资源
示例:
@Api(value = “xxx”, description = “xxx”)
value url的路径值
tags 如果设置这个值、value的值会被覆盖
description 对api资源的描述
basePath 基本路径可以不配置
position 如果配置多个Api 想改变显示的顺序位置
produces For example, "application/json, application/xml"
consumes For example, "application/json, application/xml"
protocols Possible values: http, https, ws, wss.
authorizations 高级特性认证时配置
hidden 配置为true 将在文档中隐藏
@ApiOperation
用于方法上,说明方法的作用,每一个url资源的定义
示例:
@ApiOperation(value = “xxx”,httpMethod=”POST”, notes= “xxx”,response=String.class)
value url的路径值
tags 如果设置这个值、value的值会被覆盖
notes 对api资源的描述
position 如果配置多个Api 想改变显示的顺序位置
produces For example, "application/json, application/xml"
consumes For example, "application/json, application/xml"
protocols Possible values: http, https, ws, wss.
authorizations 高级特性认证时配置
hidden 配置为true 将在文档中隐藏
response 返回的对象
responseContainer 这些对象是有效的 "List", "Set" or "Map".,其他无效
httpMethod "GET", "HEAD", "POST", "PUT", "DELETE", "OPTIONS" and "PATCH"
code http的状态码 默认 200
extensions 扩展属性
@ApiParam
用于方法、参数、字段上,请求属性
示例:
public ResponseEntity
name 属性名称
value 属性值
defaultValue 默认属性值
allowableValues 可以不配置
required 是否属性必填
access
allowMultiple 默认为false
hidden 隐藏该属性
example 示例
@ApiResponse
用于方法上,响应配置
示例:
@ApiResponse(code = 400, message = “Invalid user supplied”)
code http的状态码
message 描述
response 默认响应类 Void
reference 参考ApiOperation中配置
responseHeaders 参考 ResponseHeader 属性配置说明
responseContainer 参考ApiOperation中配置
@ApiResponses
用于方法上,响应集配置
示例:
@ApiResponses({ @ApiResponse(code = 400, message = “Invalid Order”) })
value 多个ApiResponse配置
@ResponseHeader
用于方法上,响应头设置
示例:
@ResponseHeader(name=”head1”,description=”response head conf”)
name 响应头名称
description 头描述
response 默认响应类 Void
responseContainer 参考ApiOperation中配置
@ApiImplicitParams
用于方法上,包含一组参数说明
@ApiImplicitParam
用于方法上,用在@ApiImplicitParams注解中,指定一个请求参数的各个方面
paramType 参数放在哪个地方
· header 参数在request headers 里边提交(@RequestHeader)
· query 直接跟参数完成自动映射赋值(@RequestParam)
· path 用于restful接口,以地址的形式提交数据(@PathVariable)
· body 以流的形式提交 仅支持POST(@RequestBody)
· form 以form表单的形式提交 仅支持POST
name 参数名
value 参数的汉字说明、解释
dataType 参数类型,默认String,其它值dataType=”Integer” ,无用
required 是否必要
defaultValue 参数的默认值
@ApiModel
用于类上,描述一个Model的信息(这种一般用在post创建的时候,使用@RequestBody这样的场景,请求参数无法使用@ApiImplicitParam注解进行描述的时候
@ApiModelProperty
用于方法、字段上,描述一个model的属性
@ApiIgnore
用于类,属性,方法上,忽略某项api,使用@ApiIgnore
WMS配置Swagger
找到pom.xml中找到,并修改版本号,
<classmate.version>1.3.1</classmate.version>
修改web.xml,添加如下内容:
<servlet-mapping> <servlet-name>springMvc</servlet-name> <url-pattern>/swagger/*</url-pattern> <url-pattern>/api-docs</url-pattern> </servlet-mapping>
修改 spring-mvc.xml ,添加内容如下:
<bean class="com.zzjee.swagger.SwaggerConfig" /> <mvc:resources mapping="swagger-ui.html" location="classpath:/META-INF/resources/" /> <mvc:resources mapping="webjars/**" location="classpath:/META-INF/resources/webjars/" />
修改 spring-mvc.xml ,添加内容如下:
修改登录页代码
测试
http://localhost:8081/jeewms/swagger/swagger-ui.html
内部执行了如下操作:
结果如图:
<!-- 此插件生成markdown、ASCIIDOC、wiki格式-->
<!-- 执行命令 mvn swagger2markup:convertSwagger2markup-->
<plugin>
<groupId>io.github.swagger2markup</groupId>
<artifactId>swagger2markup-maven-plugin</artifactId>
<version>1.3.7</version>
<configuration>
<!-- api-docs访问url -->
<swaggerInput>http://localhost:8081/jeewms/swagger/v2/api-docs</swaggerInput>
<!-- 生成为单个文档,输出路径-->
<outputFile>src/docs/api</outputFile>
<!-- 生成为多个文档,输出路径 -->
<!--<outputDir>src/docs/</outputDir>-->
<config>
<!-- wiki格式文档 -->
<!--<swagger2markup.markupLanguage>CONFLUENCE_MARKUP</swagger2markup.markupLanguage>-->
<!-- ascii格式文档 -->
<swagger2markup.markupLanguage>ASCIIDOC</swagger2markup.markupLanguage>
<!-- markdown格式文档 -->
<!--<swagger2markup.markupLanguage>MARKDOWN</swagger2markup.markupLanguage>-->
<swagger2markup.pathsGroupedBy>TAGS</swagger2markup.pathsGroupedBy>
</config>
</configuration>
</plugin>
<!--此插件生成HTML和PDF-->
<!-- 执行命令 mvn generate-resources -->
<plugin>
<groupId>org.asciidoctor</groupId>
<artifactId>asciidoctor-maven-plugin</artifactId>
<version>2.1.0</version>
<!-- Include Asciidoctor PDF for pdf generation -->
<dependencies>
<dependency>
<groupId>org.asciidoctor</groupId>
<artifactId>asciidoctorj-pdf</artifactId>
<version>1.5.4</version>
</dependency>
<dependency>
<groupId>org.jruby</groupId>
<artifactId>jruby-complete</artifactId>
<version>9.2.17.0</version>
</dependency>
</dependencies>
<!-- Configure generic document generation settings -->
<configuration>
<sourceDirectory>src/docs</sourceDirectory>
<!-- <sourceHighlighter>coderay</sourceHighlighter>-->
<attributes>
<toc>left</toc>
</attributes>
</configuration>
<!-- Since each execution can only handle one backend, run
separate executions for each desired output type -->
<executions>
<execution>
<id>output-pdf</id>
<phase>generate-resources</phase>
<goals>
<goal>process-asciidoc</goal>
</goals>
<configuration>
<backend>pdf</backend>
<outputDirectory>src/docs/pdf/</outputDirectory>
</configuration>
</execution>
<execution>
<id>output-html</id>
<phase>generate-resources</phase>
<goals>
<goal>process-asciidoc</goal>
</goals>
<configuration>
<backend>html5</backend>
<outputDirectory>src/docs/html/</outputDirectory>
</configuration>
</execution>
</executions>
</plugin>