系列文章
SpringBoot 01 —— HelloSpringBoot、yaml配置、数据校验、多环境切换
SpringBoot 02 —— Web简单探究、员工管理系统
SpringBoot 03 —— Spring Security
SpringBoot 04 —— Shiro
SpringBoot 05 —— Swagger
SpringBoot 06 —— 异步任务、邮件任务、定时任务
SpringBoot 07 —— 分布式:Dubbo+Zookeeper
十三、Swagger
1、简介
Swagger是一款RESTFUL接口的文档在线自动生成+功能测试功能软件。Swagger是一个规范和完整的框架,用于生成、描述、调用和可视化RESTful风格的Web服务。目标是使客户端和文件系统作为服务器以同样的速度来更新文件的方法,参数和模型紧密集成到服务器。
简单点来讲就是说,swagger是一款可以根据resutful风格生成的生成的接口开发文档,并且支持做测试的一款中间软件。
为什么要用Swagger?
- 对于后端开发人员来说
- 不用再手写WiKi接口拼大量的参数,避免手写错误
- 对代码侵入性低,采用全注解的方式,开发简单
- 方法参数名修改、增加、减少参数都可以直接生效,不用手动维护
- 缺点:增加了开发成本,写接口还得再写一套参数配置
- 对于前端开发来说
- 后端只需要定义好接口,会自动生成文档,接口功能、参数一目了然
- 联调方便,如果出问题,直接测试接口,实时检查参数和返回值,就可以快速定位是前端还是后端的问题
- 对于测试
- 对于某些没有前端界面UI的功能,可以用它来测试接口
- 操作简单,不用了解具体代码就可以操作
2、SpringBoot集成Swagger
1、新建SpringBoot项目,添加Web模块,导入依赖。
<!-- 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>
2、编写一个Controller
package com.zcy.controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class MyController {
@RequestMapping("/hello")
public String hello(){
return "hello";
}
}
3、配置Swagger
package com.zcy.config;
import org.springframework.context.annotation.Configuration;
import springfox.documentation.swagger2.annotations.EnableSwagger2;
//@Configuration就是一个@Component
@Configuration
@EnableSwagger2//开启Swagger2
public class SwaggerConfig {
}
4、测试运行:http://localhost:8080/swagger-ui.html
![image-20210331152704567](https://i-blog.csdnimg.cn/blog_migrate/99254ac77a0bab4b5c69c2b33f248952.png)
这个页面是Swagger内置的,具体看这个包:
![image-20210331170137560](https://i-blog.csdnimg.cn/blog_migrate/dfcad2142afff219f0fa23ddf29dd042.png)
3、配置基本信息
设置初始页面的信息
package com.zcy.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
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;
import java.util.ArrayList;
//@Configuration就是一个@Component
@Configuration
@EnableSwagger2//开启Swagger2
public class SwaggerConfig {
//配置Swagger
@Bean
public Docket docket(){
return new Docket(DocumentationType.SWAGGER_2).apiInfo(apiInfo());
}
//配置Swagger信息
private ApiInfo apiInfo(){
//作者信息
Contact contact = new Contact("ZCY", "https://blog.csdn.net/qq_39763246", "1142729000@qq.com");
//参数依次是:标题、描述、版本、服务条款、联系人、执照、执照链接
return new ApiInfo(
"ZCY的SwaggerAPI文档",
"Swagger学习记录",
"v1.0",
"https://blog.csdn.net/qq_39763246",
contact,
"Apache 2.0",
"http://www.apache.org/licenses/LICENSE-2.0",
new ArrayList());
}
}
效果:
![image-20210331165829315](https://i-blog.csdnimg.cn/blog_migrate/577cc728a9679aa404c82b505343c2cc.png)
4、扫描接口、开关、分组
扫描接口
可以发现,默认情况下Swagger帮我们把所有接口的扫描了(即所有Controller)
![image-20210331170248685](https://i-blog.csdnimg.cn/blog_migrate/f14192112ddb25c86c588c4433a25db8.png)
现在我们要实现自定义扫描接口(Controller)
修改docket()方法
//@Configuration就是一个@Component
@Configuration
@EnableSwagger2//开启Swagger2
public class SwaggerConfig {
//配置Swagger
@Bean
public Docket docket(){
return new Docket(DocumentationType.SWAGGER_2)
.apiInfo(apiInfo())
//.enable(false) //这样就关闭了Swagger,默认是打开的。
.select()
/**apis 设置要扫描的接口(controller)。
* 具体参数如下:
* basePackage:指定要扫描的包(常用)
* any:扫描全部(默认)
* none:不扫描
* withClassAnnotation:扫描带有指定注解的接口(controller),且该注解在类上。例如RestController.class
* withMethodAnnotation:扫描带有指定注解的接口(controller),且该注解在方法上,例如GetMapping.class
*/
.apis(RequestHandlerSelectors.basePackage("com.zcy.controller"))//扫描所有controller包下的
/**
* paths 过滤指定路径
* ant:常用,
* any:过滤所有
* none:不过滤
* regex:正则过滤
*/
.paths(PathSelectors.ant("/hello/2"))//此时/hello/1就不会被扫描
.build();
}
//配置Swagger信息
private ApiInfo apiInfo(){
//作者信息
Contact contact = new Contact("ZCY", "https://blog.csdn.net/qq_39763246", "1142729000@qq.com");
return new ApiInfo(
"ZCY的SwaggerAPI文档",
"Swagger学习记录",
"v1.0",
"https://blog.csdn.net/qq_39763246",
contact,
"Apache 2.0",
"http://www.apache.org/licenses/LICENSE-2.0",
new ArrayList());
}
}
@RestController
public class MyController {
@RequestMapping("/hello/1")
public String hello1(){
return "hello1";
}
@RequestMapping("/hello/2")
public String hello2(){
return "hello2";
}
}
由于过滤中只有/hello/2,所有现在只能扫描到/hello/2的,/hello/1就不会被扫描。
![image-20210331175241754](https://i-blog.csdnimg.cn/blog_migrate/0790c0d3413601e4f954c8b497f03936.png)
开关
现在实现这么一个场景:我只希望Swagger在开发时使用,而在发布后不使用,该如何去做呢?
- 判断当前是不是开发环境,flag=false
- 注入enable(flag)
1、添加两个配置文件:application-pro.properties(生产环境)和application-dev.properties(开发环境)
# 生产环境
# 应用名称(可省略)
spring.application.name=pro
# 应用服务 WEB 访问端口
server.port=8082
# 开发环境
# 应用名称(可省略)
spring.application.name=dev
# 应用服务 WEB 访问端口
server.port=8081
2、在主配置文件中选择激活 application.properties
# 开发环境
# 应用名称
spring.application.name=dev
# 应用服务 WEB 访问端口
server.port=8081
3、在SwaggerConfig
的docket
中判断当前环境
//配置Swagger
@Bean
public Docket docket(Environment environment){
//设置要显示的Swagger环境
Profiles dev = Profiles.of("pro");
//获取当前项目的环境:acceptsProfiles是监听,判断是否处于自己设定的环境(pro)中。
boolean flag = environment.acceptsProfiles(dev);
return new Docket(DocumentationType.SWAGGER_2)
.apiInfo(apiInfo())
.enable(flag) //判断当前是否是生产环境
.select()
.apis(RequestHandlerSelectors.basePackage("com.zcy.controller"))
.paths(PathSelectors.ant("/hello/2"))//此时/hello/1就不会被扫描
.build();
}
结果:由于主配置文件中激活的是开发环境(dev),所以关闭了Swagger。
分组
在SwaggerConfig中,我们通过Docket来配置扫描包,实际上我们可以写多个Docket来扫描不同的包。针对不同的开发者,来扫描自己的Controller。
利用方法groupName("xxx")
@Bean
public Docket docket1(){return new Docket(DocumentationType.SWAGGER_2).groupName("A");}
@Bean
public Docket docket2(){return new Docket(DocumentationType.SWAGGER_2).groupName("B");}
@Bean
public Docket docket3(){return new Docket(DocumentationType.SWAGGER_2).groupName("C");}
![image-20210401092650915](https://i-blog.csdnimg.cn/blog_migrate/79ee0acf4a2ce2deaefb582d489bdc76.png)
5、接口注释和测试
这一节才是Swagger真正有意义的地方,由于现在大都是前后端分离的项目,因此不同部门的开发人员常常会因为沟通、联调问题而出现“打架”,Swagger的优点就能解决:
- Swagger可以给难以理解的属性、接口增加注释,使得前端人员也方便理解。
- Swagger的接口文档是实时更新的。
- Swagger可以在线测试请求。
现在讲一下在Swagger UI界面的Controller和Model的作用。
1、先建立一个实体类 User(即Model)
@ApiModel("用户实体类")
public class User {
@ApiModelProperty("用户名")
public String username;//如果用private,属性就不会显示在Swagger中。
@ApiModelProperty("密码")
public String password;
public User(String username, String password) {
this.username = username;
this.password = password;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
}
2、修改一下MyController
@RestController
public class MyController {
@ApiOperation("控制类1")//@ApiOperation 给方法添加Swagger注释
@PostMapping("/controller1")
public String controller1(){
return "controller1";
}
@ApiOperation("控制类2")
@PostMapping("/controller2")//@ApiParam 给Swagger参数添加注释
public String controller2(@ApiParam("参数1") String param1, @ApiParam("参数2") String param2){
return "controller2:"+param1+", "+param2;
}
//只要Controller中有返回一个实体类,Swagger就会扫描到。
@RequestMapping("/user")//这里用RequestMapping,就会被扫出Post、Get、Put、Delete等全部类型。
public User user(User user){
return user;
}
}
3、修改docket里的扫描包和过滤
//配置Swagger
@Bean
public Docket docket(Environment environment){
Profiles dev = Profiles.of("pro");
boolean flag = environment.acceptsProfiles(dev);
return new Docket(DocumentationType.SWAGGER_2)
.apiInfo(apiInfo())
.enable(flag)
.select()
.apis(RequestHandlerSelectors.basePackage("com.zcy.controller"))
.paths(PathSelectors.ant("/**"))
.build();
}
4、扫描结果(带着注释)
![image-20210401102236119](https://i-blog.csdnimg.cn/blog_migrate/3d052ea94a3d645e42146f5c0adc3e75.png)
5、进行在线接口测试(这里以controller2为例)
- 点击尝试:
![image-20210401102250809](https://i-blog.csdnimg.cn/blog_migrate/b1605f217dc803ec1761062ffe09d319.png)
-
输入参数:
-
执行: