一. 什么是swagger
Swagger 是一个规范和完整的框架,用于生成、描述、调用以及可视化的 Restful 风格的 Web 服务。
简单的理解:是一款 REST API 文档生成工具,生成在线的接口文档,方便接口测试。
二.为什么使用swagger
前后端分离开发时,为了方便前后端接口调用规范,需要提供一个接口文档,但是维护这个接口文档是一个及其繁琐的事情,可能一不小心就忘记更新该文档从而导致前后端接口调用失败。
Swagger 就是为了解决这个问题而出现的(在线接口文档),其在接口方法上定义注解,并根据注解形成一个 html 页面,每次接口修改,这个 html 页面就会发生相应的改变,从而保证了接口文档的正确性。通过该 html 页面,可以很方便、清楚的知道这个接口的功能,并测试
三、SpringBoot 整合 Swagger
(1) 添加依赖
<dependency> <groupId>io.springfox</groupId> <artifactId>springfox-swagger2</artifactId> <version>2.9.2</version> </dependency> <!-- https://mvnrepository.com/artifact/io.springfox/springfox-swagger-ui --> <dependency> <groupId>io.springfox</groupId> <artifactId>springfox-swagger-ui</artifactId> <version>2.9.2</version> </dependency>
(2) 添加配置类
package cn.itrip.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import springfox.documentation.builders.ApiInfoBuilder;
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;
/**
* Swagger配置类
*/
@Configuration
@EnableSwagger2
public class SwaggerConfig {
/**
* 通过createRestApi函数创建Docket的Bean之后,
* apiInfo()用来创建该Api的基本信息(这些基本信息会展现在文档页面中)
* select()函数返回一个ApiSelectorBuilder实例用来控制哪些接口暴露给Swagger来展现,
* apis()函数扫描所有Controller中定义的API, 并产生文档内容(除了被@ApiIgnore指定的请求)
* @return
*/
@Bean
public Docket createRestApi() {
return new Docket(DocumentationType.SWAGGER_2)
.pathMapping("/")
.select()
//指定包下的类,才生成接口文档
.apis(RequestHandlerSelectors.basePackage("cn.itrip.controller"))
.paths(PathSelectors.any())
.build().apiInfo(new ApiInfoBuilder()
.title("爱旅行-主业务模块API")
.description("处理酒店、酒店房间、评论、订单业务")
.version("版本号: 1.0")
//.contact(new Contact("佚名","blog.bdqn.net","yiming@qq.com"))
.license("The Apache License")
//.licenseUrl("http://www.baidu.com")
.build());
//license 和licenseUrl(许可访问地址) 可以不加
}
}
(3)配置完之后进入 http://{path}:{port}/swagger-ui.html 即可查看controller中的接口信息,并按照Docket中配置的规则进行展示。
四、Swagger常用注解
1、@ApiModel
使用场景:用于JavaBean的类上面,表示此 JavaBean 整体的信息, 一般用在post请求,使用 @RequestBody 的场景,即请求参数无法使用 @ApiImplicitParam 注解进行描述的时候
概述:提供有关swagger模型的其它信息,类将在操作中用作类型时自动内省
属性名称 | 数据类型 | 默认值 | 说明 |
---|---|---|---|
value | String | 类名 | 为模型提供备用名称 |
description | String | "" | 提供详细的类描述 |
parent | Class<?> parent() | Void.class | 为模型提供父类以运行描述继承关系 |
discriminator | String | "" | 支持模型继承和多态,使用鉴别器的字段名称,可以断言需要使用哪个子类型 |
subTypes | Class<?>[] | {} | 从模型继承的子类型数组 |
reference | String | "" | 指定对应类型定义的引用,覆盖指定的任何其他元数据 |
示例:
/**
* Student类 学生实体类
*/
@ApiModel(value = "Student",description = "学生实体类")
public class Student implements Serializable {
}
2、@ApiModelProperty
使用场景:使用在被 @ApiModel 注解的模型类的属性上。表示对model属性的说明或者数据操作更改
概述:添加和操作模型属性的数据
属性名称 | 数据类型 | 默认值 | 说明 |
---|---|---|---|
value | String | "" | 属性简要说明 |
name | String | "" | 重写属性名称 |
allowableValues | String | "" | 限制参数可接收的值,三种方法,固定取值,固定范围 |
access | String | "" | 过滤属性 |
notes | String | "" | 目前尚未使用 |
dataType | String | "" | 参数的数据类型,可以是类名或原始数据类型,此值将覆盖从类属性读取的数据类型 |
required | boolean | false | 是否为必传参数(false:非必传参数;true:必传参数) |
position | int | "" | 运行在模型中显示排序属性 |
hidden | boolean | false | 隐藏模型属性(false:不隐藏;true:隐藏) |
example | String | "" | 属性的示例值 |
readOnly | boolean | false | 指定模型属性为只读(false:非只读;true:只读) |
reference | String | "" | 指定对应类型定义的引用,覆盖指定的任何其他元数据 |
allowEmptyValue | boolean | false | 运行穿空值(false:不允许传空值;true:运行传空值) |
extensions | Extension[] | {@Extension(properties={@ExtensionProperty(name = "",value = "")})}; | 关联注解 |
示例:
//注:也可以不写value,如下 :
@ApiModelProperty("学号")
1 @ApiModelProperty(value = "学号")
2 private Integer id; //学号
3 @ApiModelProperty(value = "姓名")
4 private String name; //姓名
5 @ApiModelProperty(value = "成绩")
6 private Integer score; //成绩
7 @ApiModelProperty(value = "籍贯")
8 private String birthplace; //籍贯
9 //日期的格式 年-月-日
10 @ApiModelProperty(value = "生日")
11 @DateTimeFormat(pattern = "yyyy-MM-dd")
12 private Date birthday; //生日
页面效果
@ApiModel与@ApiModelProperty效果
3.@Api
放在请求的类上,与 @Controller 并列,说明类的作用,如用户模块,订单类等。
示例:
@Api(tags = "爱旅行-主业务模块:评论业务")
@RestController
@RequestMapping("api/comment")
public class HotelCommentController {
}
4.@ApiOperation
使用场景:使用在方法上,表示一个http请求的操作
概述:用来表示Controller类下的http请求方法
属性名称 | 数据类型 | 默认值 | 说明 |
---|---|---|---|
value | String | 属性简要说明 | |
notes | String | "" | 备注说明 |
tags | String | {""} | 可重新分组 |
response | Class<?> response() | Void.class | 用于描述消息有效负载的可选响应类,对应于响应消息对象的 schema 字段 |
responseContainer | String | "" | 声明响应的容器,有效值为List,Set,Map,任何其他值都将被忽略 |
responseReference | String | "" | 声明响应的引用 |
httpMethod | String | "" | http请求方式 |
position | int | 0 | 运行在模型中显示排序属性 |
nickname | String | "" | 昵称 |
produces | String | "" | For example, "application/json, application/xml" |
consumes | String | "" | For example, "application/json, application/xml" |
protocols | String | "" | Possible values: http, https, ws, wss. |
authorizations | Authorization[] | {@Authorization("")} | 高级特性认证时配置 |
hidden | boolean | false | 是否隐藏 |
responseHeaders | ResponseHeader[] | {@ResponseHeader(name = "",response = Void.class)}; | 可能响应的 header 列表 |
code | int | 200 | http状态码 |
extensions | Extension[] | {@Extension(properties = {@ExtensionProperty(name = "",value = "")})}; | 关联注解 |
ignoreJsonView | boolean | false | 是否忽略json视图 |
示例:
@ApiOperation(value = "根据酒店id查询各类评论数量", httpMethod = "GET",
protocols = "HTTP",produces = "application/json",
response = Dto.class,notes = "根据酒店id查询评论数量(全部评论、值得推荐、有待改善、有图片)"+
"<p>成功:success = ‘true’ | 失败:success = ‘false’ 并返回错误码,如下:</p>" +
"<p>错误码:</p>"+
"<p>100014 : 获取酒店总评论数失败 </p>"+
"<p>100015 : 获取酒店有图片评论数失败</p>"+
"<p>100016 : 获取酒店有待改善评论数失败</p>"+
"<p>100017 : 获取酒店值得推荐评论数失败</p>"+
"<p>100018 : 参数hotelId为空</p>")
@GetMapping("getcount/{hotelId}")
public Dto getCommentCount(@PathVariable("hotelId") Long hotelId){
}
5.@ApiImplicitParams
使用场景:用在请求的方法上,包含一组参数说明
6.@ApiImplicitParam
使用场景:对单个参数的说明
参数: | 说明 | 参数值 | 参数值的说明 | 参数的注解 |
name | 参数名 | |||
value | 参数说明 | |||
paramType | 参数格式. 值: (字符串格式) | |||
header | 用于定义请求头参数 | @RequestHeader | ||
query | 用于定义普通请求参数, 默认 | @RequestParam | ||
path | 用于定义restful路径参数 | @PathVariable | ||
body | 用于定义请求体参数 | @RequestBody User user | ||
form | 用于定义表单参数 | |||
dataType | 参数类型. 默认为字符串. 也可以自定义, 如int, double | |||
required | 参数是否必填, 默认false | |||
defaultValue | 参数的默认值, 方便测试使用 |
示例:
@ApiImplicitParams({
@ApiImplicitParam(paramType="path",required=true,value="订单id",name="orderId",dataType="long"),
@ApiImplicitParam(paramType="header",required=true,value="token字符串",name="token")
})
@GetMapping("getpersonalorderinfo/{orderId}")
public Dto getPersonalOrderInfo(@PathVariable("orderId") Long orderId,@RequestHeader("token") String token){
}
7.@ApiResponses
使用场景: 方法返值的说明
8.@ApiResponse
使用场景: 返回值每个参数的说明
参数: | 说明 |
code | 数字,例如400 |
message | 信息,例如"请求参数没填好" |
response | 抛出异常的类 |
示例:
@ApiResponses({
@ApiResponse(code = 200, message = "执行成功")
})
public Object test3(UserVo userVo){
return DtoUtil.returnSuccess(userVo);
}
五、将swagger文档导入postman
1. 将swagger-ui.html 页面中的文档路径复制, 打开postman--> import -->link --> 粘贴路径-->continue-->import
2. 在Collections 或APIS中可以看到导入的接口数据
3. 修改路径:选中接口文档 , 右键, Edit --> variables
六、导出swagger接口文档
1、导入模块依赖
pom.xml文件
<!-- swagger2markup模块 -->
<dependency>
<groupId>io.github.swagger2markup</groupId>
<artifactId>swagger2markup</artifactId>
<version>1.3.1</version>
</dependency>
2、新增测试类
在src/test/java/com/example/demo目录下新建测试类SwaggerTo
SwaggerTo
@RunWith(SpringRunner.class) //测试类要使用注入的类
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.DEFINED_PORT) //用于单元测试
public class SwaggerTo {
}
3、新增测试方法
generateMarkdownDocs()
/**
* 生成Markdown格式文档
* @throws Exception
*/
@Test
public void generateMarkdownDocs() throws Exception {
// 输出Markdown格式
Swagger2MarkupConfig config = new Swagger2MarkupConfigBuilder()
.withMarkupLanguage(MarkupLanguage.MARKDOWN) //输出格式:ASCIIDOC,MARKDOWN,CONFLUENCE_MARKUP
.withOutputLanguage(Language.ZH) //语言类型:中文(ZH) 默认英文(EN)
.withPathsGroupedBy(GroupBy.TAGS) //Api排序规则
.withGeneratedExamples()
.withoutInlineSchema()
.build();
Swagger2MarkupConverter.from(new URL("http://localhost:8080/v2/api-docs?group=user")) //url,注意端口号与分组
.withConfig(config)
.build()
.toFolder(Paths.get("src/docs/markdown/generated")); //生成文件的存放路径,生成多个文件
}
此时在src/docs/markdown/generated目录下就会生成definitions.md、overview.md、paths.md、security.md文件,即生成的markdown文件
generateMarkdownDocsToFile()
/**
* 生成Markdown格式文档,并汇总成一个文件
* @throws Exception
*/
@Test
public void generateMarkdownDocsToFile() throws Exception {
// 输出Markdown到单文件
Swagger2MarkupConfig config = new Swagger2MarkupConfigBuilder()
.withMarkupLanguage(MarkupLanguage.MARKDOWN) //输出格式:ASCIIDOC,MARKDOWN,CONFLUENCE_MARKUP
.withOutputLanguage(Language.ZH) //语言类型:中文(ZH) 默认英文(EN)
.withPathsGroupedBy(GroupBy.TAGS) //Api排序规则
.withGeneratedExamples()
.withoutInlineSchema()
.build();
Swagger2MarkupConverter.from(new URL("http://localhost:8080/v2/api-docs?group=user")) //url,注意端口号与分组
.withConfig(config)
.build()
.toFile(Paths.get("src/docs/markdown/generated/all")); //生成文件的存放路径,汇总为一个文件
}
此时在src/docs/markdown/generated目录下就会生成all.md文件,即生成的markdown文件
注意:
-
如果在Swagger2Config类里声明了分组,即Docket方法有.groupName("user"),那么测试方法中url路径后面需要添加?group=user。如果Swagger2Config类中未声明分组,则测试方法中url路径不需要添加?group=user
-
在使用测试方法生成文件的时候需要关闭项目,否则会提示端口被占用
-
可以修改Swagger2MarkupConfig.withMarkupLanguage()方法内的参数值来生成不同的文件格式,修改Swagger2MarkupConverter.toFile()方法内的参数值提供对应的生成文件存放路径
-
definitions.md存放Models相关信息,overview.md存放文档概览相关信息,paths.md存放controller相关信息,security.md存放与身份认证相关的信息4、导出文档部分内容
-
all.md
-
4、导出文档部分内容
all.md
-