Swagger学习笔记
1 Swagger简介
1.1 引言
随着互联网技术的发展,现在的系统架构基本都是有原来的后端渲染变成了:前端渲染,前后端分离的形态,而且前端技术和后端技术再各自的道路上越走越远。
前端和后端的唯一联系,变成了API接口,API文档变成了前后端开发人员联系的纽带,变得越来越重要,swagger就是一款让你更好的书写API文档的框架。
相信无论是前端还是后端开发,都或多或少地被接口文档折磨过。前端经常抱怨后端给的文档接口与实际情况不一致。
后端又觉得编写及维护接口文档会耗费不少精力,经常来不及更新,其实无论是前端调用后端,还是后端调用后端,都期望有一个好的接口文档。但是这个接口文档对于程序员来说,就跟注释一样,经常会抱怨别人写的代码没有写注释,然而自己写起代码来,最讨厌的,也是写注释。所以仅仅只通过强制来规范大家是不够的,随着时间推移,版本迭代,接口文档往往很容易就跟不上代码了。
1.2 什么是Swagger
发现了痛点就要去找解决方案。解决方案用的人多了,就成了标准的规范,这就是Swagger的由来。通过这套规范,你只需要安装它的规范去定义接口及接口相关的信息。再通过Swagger衍生出来的一系列项目和工具,就可以做到生成各种格式的接口文档。生成多种语言的客户端和服务端代码,以及在线接口调试页面等等。这样,如果按照新的开发模式,在开发新版本或者迭代版本的时候,只需要更新Swagger描述文件,就可以自动生成接口文档和客户端服务端代码,做到调用端代码、服务端代码以及接口文档的一致性。
但即便如此,对于许多开发来说,编写这个yml或json格式的描述文件,本身也是有一定负担的工作,特别是在后面持续迭代开发的时候,往往会忽略更新这个描述文件,直接更改代码。久而久之,这个描述文件也和实际项目渐行渐远,基于改描述文件生成的接口文档也失去了参考意义。所以作为Java服务端的大一统框架Spring,迅速将Swagger规范纳入自身的标准,建立了Spring-swagger项目,后面改成了现在的Springfox,可以描述相关的代码,生成该描述文件,进而生成与代码一致的接口文档和客户端代码。这种通过代码生成接口文档的形式,在后面需求持续迭代的项目中,显得尤为重要和高效。
。总结:Swagger就是一个用来定义接口标准,接口规范,同时能根据你的代码自动生成接口说明文档的一个工具。
2 环境搭建
2.1 引入依赖
<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>
3.2 编写Swagger配置类
package com.tangguanlin.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.service.ApiInfo;
import springfox.documentation.service.Contact;
import springfox.documentation.spi.DocumentationType;
import springfox.documentation.spring.web.plugins.Docket;
import springfox.documentation.swagger2.annotations.EnableSwagger2;
/**
* 说明:swagger配置类
* 作者:汤观林
* 日期:2021年12月31日 18时
*/
@Configuration
@EnableSwagger2
public class SwaggerConfig {
@Bean
public Docket createRestApi(){
//开发文档的联系人信息
Contact contact = new Contact("小陈","www.baizhiedu.xin","xiaochen@163.com");
//接口文档描述信息
ApiInfo apiInfoBuilder = new ApiInfoBuilder()
.title("标题:SpringBoot整合Swagger使用") //接口文档标题
.description("SpringBoot整合Swagger,详细信息...") //详细信息
.version("1.1") //版本
.contact(contact)
.license("The Baizhi License") //随便写
.licenseUrl("http://www.baizhiedu.com") //随便写
.build();
//Docket容器
return new Docket(DocumentationType.SWAGGER_2) //规范2
.pathMapping("/")
.select()
.apis(RequestHandlerSelectors.basePackage("com.tangguanlin.controller")) //扫描哪个包下的接口
.paths(PathSelectors.any())
.build()
.apiInfo(apiInfoBuilder);
}
}
2.3 启动springboot应用
在IDEA中新建SpringBoot工程,引入依赖,加上配置类,启动。
项目结构如下:
命令行中出现“Started DemoApplication in 8.649 seconds”,则说明SpringBoot项目启动成功。
2.4 访问Swagger的UI界面
项目启动后,可以在浏览器中访问Swagger的UI界面,
访问地址为:http://localhost:8082/swagger-ui.html
Swagger UI界面上显示的文字描述就是刚才在SwaggerConfig配置类中配置的信息。
3 Swagger配置类
3.1 接口文档描述信息
//开发文档的联系人信息 姓名 个人网页 邮箱
Contact contact = new Contact("小陈","www.baizhiedu.xin","xiaochen@163.com");
//接口文档信息
ApiInfo apiInfo = new ApiInfoBuilder()
.title("标题:SpringBoot整合Swagger使用") //接口文档标题
.description("SpringBoot整合Swagger,详细信息...") //详细信息
.version("1.1") //版本
.contact(contact)
.license("The Baizhi License") //随便写
.licenseUrl("http://www.baizhiedu.com") //随便写
.build();
运行结果:
3.2 接口扫描策略
3.2.1 扫描所有接口
RequestHandlerSelectors.any()
3.2.2 扫描指定包
扫描com.tangguanlin.controller包下的接口
RequestHandlerSelectors.basePackage("com.tangguanlin.controller")
3.2.3 基于类的扫描
基于类上面@RestController注解的扫描
RequestHandlerSelectors.withClassAnnotation(RestController.class)
Controller类:
SwaggerConfig配置类:
基于类上@RestController注解的扫描
//Docket容器
return new Docket(DocumentationType.SWAGGER_2) //规范2
.pathMapping("/")
.select()
//基于类上@RestController注解的扫描
.apis(RequestHandlerSelectors.withClassAnnotation(RestController.class)) //扫描哪个包下的接口
.paths(PathSelectors.any())
.build()
.apiInfo(apiInfo);
}
运行结果:
3.2.4 基于方法的扫描
RequestHandlerSelectors.withMethodAnnotation()
运行结果:
3.3 忽略接口参数
忽略String类型的参数
.ignoredParameterTypes(String.class)
SwaggerConfig配置类:
//Docket容器
return new Docket(DocumentationType.SWAGGER_2) //规范2
//忽略String类型的参数
.ignoredParameterTypes(String.class)
.pathMapping("/")
.select()
//扫描哪个接口的包
.apis(RequestHandlerSelectors.basePackage("com.tangguanlin.controller")) //扫描哪个包下的接口
.paths(PathSelectors.any())
.build()
.apiInfo(apiInfo);
运行结果:
3.4 控制Swagger是否展示
.enable(true) //swagger展示
.enable(false) //swagger不展示
配置类SwaggerConfig.java
//Docket容器
return new Docket(DocumentationType.SWAGGER_2) //规范2
.enable(false) //swagger不展示
.pathMapping("/")
.select()
//扫描哪个接口的包
.apis(RequestHandlerSelectors.basePackage("com.tangguanlin.controller")) //扫描哪个包下的接口
.paths(PathSelectors.any())
.build()
.apiInfo(apiInfo);
运行结果:
3.5 Swagger分组
指定组的名称
.groupName("MongoDB") //组名为MongoDB的组
比如,分成2个组展示:
@Bean
public Docket docketMongoDB(){
//Docket容器
return new Docket(DocumentationType.SWAGGER_2) //规范2
.groupName("MongoDB") //组名1:MongoDB
.pathMapping("/")
.select()
//扫描哪个接口的包
.apis(RequestHandlerSelectors.basePackage("com.tangguanlin.controller")) //扫描哪个包下的接口
.paths(PathSelectors.any())
.build()
.apiInfo(apiInfo);
}
@Bean
public Docket docketHello(){
//Docket容器
return new Docket(DocumentationType.SWAGGER_2) //规范2
.groupName("用户组") //组名2:用户组
.pathMapping("/")
.select()
//扫描哪个接口的包
.apis(RequestHandlerSelectors.basePackage("com.tangguanlin.controller")) //扫描哪个包下的接口
.paths(PathSelectors.any())
.build()
.apiInfo(apiInfo);
}
运行结果:
4 使用Swagger构建
4.1 编写接口
在MongoDBController中编写createCollection接口
@RestController
public class MongoDBController {
@Autowired
private MongoTemplate mongoTemplate;
//创建集合
@GetMapping("/createCollection")
public void createCollection(){
mongoTemplate.createCollection("test2");
}
}
4.2 在类上加@Api注释
@RestController
@Api(tags = "MongoDB相关接口描述")
public class MongoDBController {
@Autowired
private MongoTemplate mongoTemplate;
//创建集合
@GetMapping("/createCollection")
public void createCollection(){
mongoTemplate.createCollection("test2");
}
}
4.3 在方法上加@ApiOperation注释
@RestController
@Api(tags = "MongoDB相关接口描述")
public class MongoDBController {
@Autowired
private MongoTemplate mongoTemplate;
//创建集合
@GetMapping("/createCollection")
@ApiOperation(value = "创建集合",notes = "创建集合详细描述")
public void createCollection(){
mongoTemplate.createCollection("test2");
}
}
4.4 访问Swagger的UI界面
重启项目,访问Swagger的UI界面,
可以看到Swagger的UI界面就是生成的接口文档信息。
5 Swagger注解
5.1 @Api
【作用】:用来指定接口的描述文字
【修饰范围】:用在类上
【语法】: @Api(tags = “xxxxxxxxxxxx”,notes=“xxxxxxx”)
@RestController
@Api(tags = "MongoDB相关接口描述",notes="MongoDB相关接口详细描述")
public class MongoDBController {
@Autowired
private MongoTemplate mongoTemplate;
}
运行结果:
5.2 @ApiOperation
【作用】:用来对接口中具体方法做描述
【修饰范围】:用在方法上
【语法】: @ApiOperation(value = “创建集合”,notes = “创建集合详细描述”)
//创建集合
@GetMapping("/createCollection")
@ApiOperation(value = "创建集合",notes = "创建集合详细描述")
public void createCollection(){
mongoTemplate.createCollection("test2");
}
运行结果:
5.3 @ApiImplicitParams
【作用】:用来对接口中的参数进行说明
【修饰范围】:用在方法上
5.3.1 通过form表单方式传参
//创建集合
@GetMapping("/createCollection")
@ApiOperation(value = "创建集合",notes = "创建集合详细描述")
@ApiImplicitParams({
@ApiImplicitParam(name="username",value = "用户名"),
@ApiImplicitParam(name="password",value="密码")
})
public void createCollection(String userName,String password){
mongoTemplate.createCollection("test2");
}
//创建集合
@GetMapping("/createCollection")
@ApiOperation(value = "创建集合",notes = "创建集合详细描述")
public void createCollection(User user){
mongoTemplate.createCollection("test2");
}
运行结果:
5.3.2 通过地址栏方式传参
//创建集合
@GetMapping("/createCollection/{username}/{password}")
@ApiOperation(value = "创建集合",notes = "创建集合详细描述")
@ApiImplicitParams({
@ApiImplicitParam(name="username",value = "用户名",paramType ="path"),
@ApiImplicitParam(name="password",value="密码",paramType = "path")
})
public void createCollection(@PathVariable("username") String username,
@PathVariable("password") String password){
mongoTemplate.createCollection("test2");
}
运行结果:
5.3.3 通过json格式传参
很少2个字段分开用,一般都封装成对象User进行传参
//创建集合
@GetMapping("/createCollection")
@ApiOperation(value = "创建集合",notes = "创建集合详细描述")
@ApiImplicitParams({
@ApiImplicitParam(name="username",value = "用户名",paramType = "body"),
@ApiImplicitParam(name="password",value="密码",paramType = "body")
})
public void createCollection(@RequestBody String username, @RequestBody String password){
mongoTemplate.createCollection("test2");
}
运行结果:
5.3.4 通过json格式对象传参
Person.java
package com.tangguanlin.model;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
/**
* 说明:通过json格式对象传参
* 作者:汤观林
* 日期:2022年01月01日 22时
*/
@Data
@NoArgsConstructor
@AllArgsConstructor
@ApiModel(value = "人员")
public class Person {
@ApiModelProperty(value = "用户名")
private String username;
@ApiModelProperty(value = "密码")
private String password;
}
MongoDBController.java
//创建集合
@GetMapping("/createCollection")
@ApiOperation(value = "创建集合",notes = "创建集合详细描述")
public void createCollection(@RequestBody Person person){
mongoTemplate.createCollection("test2");
}
运行结果:
5.4 @ApiModel
【作用】:用来实体对象做描述
【修饰范围】:用在实体上
【语法】: @ApiModel(value = “人员信息”)
package com.tangguanlin.model;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
/**
* 说明:@ApiModel
* 作者:汤观林
* 日期:2022年01月01日 22时
*/
@Data
@NoArgsConstructor
@AllArgsConstructor
@ApiModel(value = "人员")
public class Person {
}
5.5 @ApiModelProperty
【作用】:用来实体的字段做描述
【修饰范围】:用在实体字段上
【语法】:@ApiModelProperty(value = “密码”)
package com.tangguanlin.model;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
/**
* 说明:@ApiModelProperty
* 作者:汤观林
* 日期:2022年01月01日 22时
*/
@Data
@NoArgsConstructor
@AllArgsConstructor
@ApiModel(value = "人员")
public class Person {
@ApiModelProperty(value = "用户名")
private String username;
@ApiModelProperty(value = "密码")
private String password;
}