什么是Swagger2
当下很多公司都采取前后端分离的开发模式,前端和后端的工作由不同的工程师完成。在这种开发模式下,维持一份及时更新且完整的 API 文档将会极大的提高我们的工作效率。传统意义上的文档都是后端开发人员手动编写的,相信大家也都知道这种方式很难保证文档的及时性,这种文档久而久之也就会失去其参考意义,反而还会加大我们的沟通成本。而 Swagger 给我们提供了一个全新的维护 API 文档的方式,下面我们就来了解一下它的优点:
-
**代码变,文档变。**只需要少量的注解,Swagger 就可以根据代码自动生成 API 文档,很好的保证了
文档的时效性。
-
跨语言性,支持 40 多种语言。
-
Swagger UI 呈现出来的是一份可交互式的 API 文档,我们可以直接在文档页面尝试 API 的调用,
省去了准备复杂的调用参数的过程。
-
还可以将文档规范导入相关的工具(例如 Postman、SoapUI), 这些工具将会为我们自动地创建自
动化测试。
Swagger3
-
2017年Swagger2停止更新 → 新项目Swagger3
-
兼容Swagger2注解
-
更简单的配置
-
更高的安全性
-
不支持低版本Spring
SpringBoot集成Swagger2
环境
jdk 1.8
SpringBoot 2.3.2
Swagger 2.9.2
步骤
1.在pom.xml加入swagger2相关依赖
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger2</artifactId>
<version>2.9.2</version>
</dependency>
<!--swagger ui-->
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger-ui</artifactId>
<version>2.9.2</version>
</dependency>
2.新建Swagger2Config配置类
@Configuration//配置类
@EnableSwagger2//开启swagger2
public class Swagger2Config {
@Bean//加入ioc容器
public Docket adminApiConfig(){
//需要详情配置
return new Docket(DocumentationType.SWAGGER_2)
.apiInfo(adminApiInfo())//页面显示信息
.select()//必须有select扫描
.apis(RequestHandlerSelectors.any())
.paths(PathSelectors.any())
.build();
}
private ApiInfo adminApiInfo(){
return new ApiInfoBuilder()
.title("Swagger2UI演示")
.description("此处为描述")
.version("1.0")
.build();
}
}
3.新建Controller和值对象
@Api(tags = "用户相关接口")
@RestController
@RequestMapping("/user")
public class DemoController {
@ApiOperation("登录")
@PostMapping("/login")
public String login(@RequestBody LoginRequest user) {
if (ObjectUtils.isEmpty(user.getUsername()) ||
ObjectUtils.isEmpty(user.getPassword())) {
return "用户名或密码错误";
}
if ("swagger2".equals(user.getUsername())) {
if ("123".equals(user.getPassword())) {
return "登录成功";
} else {
return "用户名或密码错误";
}
} else {
return "用户名或密码错误";
}
}
}
@ApiModel
public class LoginRequest {
@ApiModelProperty
private String username;
@ApiModelProperty
private String 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;
}
}
4.访问测试 :http://localhost:8080/swagger-ui.html ,可以看到swagger的界面
配置扫描接口
- 构建Docket时通过select()方法配置扫描接口。
@Bean//加入ioc容器
public Docket adminApiConfig(){
//需要详情配置
return new Docket(DocumentationType.SWAGGER_2)
.apiInfo(adminApiInfo())
.select()//必须有select扫描
.apis(RequestHandlerSelectors.basePackage("com.goldwind.swagger_demo.controller"))
.paths(PathSelectors.any())
.build();
}
-
重启项目测试,由于我们配置根据包的路径扫描接口,所以我们只能看到一个类
-
除了通过包路径配置扫描接口外,还可以通过配置其他方式扫描接口,这里注释一下所有的配置方式:
any() // 扫描所有,项目中的所有接口都会被扫描到
none() // 不扫描接口
// 通过方法上的注解扫描,如withMethodAnnotation(GetMapping.class)只扫描get请求
withMethodAnnotation(final Class<? extends Annotation> annotation)
// 通过类上的注解扫描,如.withClassAnnotation(Controller.class)只扫描有controller注解的类中的接口
withClassAnnotation(final Class<? extends Annotation> annotation)
basePackage(final String basePackage) // 根据包路径扫描接口
- 除此之外,我们还可以配置接口扫描过滤:
@Bean//加入ioc容器
public Docket adminApiConfig(){
//需要详情配置
return new Docket(DocumentationType.SWAGGER_2)
.apiInfo(adminApiInfo())
.select()//必须有select扫描
.apis(RequestHandlerSelectors.basePackage("com.goldwind.swagger_demo.controller"))
// 配置如何通过path过滤,即这里只扫描请求以/swagger_demo开头的接口
.paths(PathSelectors.ant("/swagger_demo/**"))
.build();
}
- 这里的可选值还有
any() // 任何请求都扫描
none() // 任何请求都不扫描
regex(final String pathRegex) // 通过正则表达式控制
ant(final String antPattern) // 通过ant()控制
配置Swagger开关
Swagger2目前有一些接口BUG,而且为了不暴露接口,所以生产环境的时候请务必关闭Swagger2的访问
方式一:
-
通过enable()方法配置是否启用swagger,如果是false,swagger将不能在浏览器中访问了
@Bean public Docket adminApiConfig(){ return new Docket(DocumentationType.SWAGGER_2) .apiInfo(adminApiInfo()) .enable(false)//开关 .select() .apis(RequestHandlerSelectors.any()) .paths(PathSelectors.any()) .paths(PathSelectors.ant("/swagger_demo/**")) .build(); }
-
动态配置当项目处于test、dev环境时显示swagger,处于prod时不显示
@Bean public Docket docket(Environment environment) { // 设置要显示swagger的环境 Profiles of = Profiles.of("dev", "test"); // 判断当前是否处于该环境 // 通过 enable() 接收此参数判断是否要显示 boolean b = environment.acceptsProfiles(of); return new Docket(DocumentationType.SWAGGER_2) .apiInfo(adminApiInfo()) .enable(b) .select() .apis(RequestHandlerSelectors.basePackage("com.goldwind.swagger_demo.controller")) .paths(PathSelectors.ant("/swagger_demo/**")) .build(); }
方式二(推荐):
基于Profile
进行配置。我们知道@Profile
可以指定组件在哪个环境的情况下才能被注册到容器中。默认不指定,任何环境下都能注册这个组件。
我们可以通过``@Profile`注解来决定是否在指定的环境中进行注入。
@Configuration
@EnableSwagger2
@Profile({"dev","test"})
public class SwaggerConfig {
}
==优点:==利用Spring Boot的特性,根本不用去初始化组件,更加省事和安全
配置分组
-
通过groupName()方法配置分组
@Bean public Docket docket() { return new Docket(DocumentationType.SWAGGER_2).apiInfo(apiInfo()) .groupName("业务模块") // 配置分组 // 省略配置.... }
-
配置多个分组
@Bean public Docket docket1(){ return new Docket(DocumentationType.SWAGGER_2).groupName("业务模块"); } @Bean public Docket docket2(){ return new Docket(DocumentationType.SWAGGER_2).groupName("工具模块"); } @Bean public Docket docket3(){ return new Docket(DocumentationType.SWAGGER_2).groupName("管理模块"); }
实体类配置
- 实体类
@ApiModel("用户登录对象")//为类添加注释
public class LoginRequest {
@ApiModelProperty("用户名")//为类属性添加注释
private String username;
@ApiModelProperty("密码")
private String password;
}
- 只要这个实体在请求接口的返回值上(即使是泛型),都能映射到实体项中:
@ApiOperation("获取用户")
@PostMapping("/get_user")
public User getUser(){
return new User();
- 重启查看
常用注解
Swagger的所有注解定义在io.swagger.annotations
包下
下面列一些经常用到的,未列举出来的可以另行查阅说明:
1.@Api()
用在请求的类上,表示对类的说明
@Api(tags = "测试用例1")
@Controller
public class swaggerTestUse(){
}
2.@ApiOperation()
用在请求的方法上,说明方法的作用
@Api("测试用例1")
@Controller
public class swaggerTestUse(){
@ApiOperation(value = "apiOperationSwaggerTest", notes = "apiOperationSwagger测试")
public void apiOperationSwaggerTest(){
}
}
3.@ApiParam()
作用于变量,说明变量的作用
@Api("测试用例1")
@Controller
public class swaggerTestUse(){
@ApiOperation(value = "apiOperationSwaggerTest", notes = "apiOperationSwagger测试")
public void apiOperationSwaggerTest(@ApiParam(name = "id", value = "id入参",
required = true) Integer id){
}
}
4.@ApiModel()
用在实体类上,描述实体类的含义
@ApiModel(description = "测试实体类", value = "测试实体类")
public class LoginRequest {
···
}
5.@ApiModelProperty()
用在属性上,描述响应类的属性
@ApiModel(description = "测试实体类", value = "测试实体类")
public class LoginRequest {
@ApiModelProperty(name = "userName", value = "用户名", required = false, exmaple = "小明")
private String userName;
}
6.@ApiImplicitParams()和@ApiImplicitParam()
用在请求的方法上,表示一组参数说明
@Api("测试用例1")
@Controller
public class swaggerTestUse(){
@ApiOperation(value = "apiOperationSwaggerTest", notes = "apiOperationSwagger测试")
@ApiImplicitParams({
@ApiImplicitParam(name = "id", value = "id入参", required = true, dataType = "Integer", paramType = "query"),
@ApiImplicitParam(name = "brand", value = "brand", required = true, dataType = "Brand", paramType = "body")
})
public void apiOperationSwaggerTest(Integer id, Brand band){
}
}
@ApiImplicitParam:用在@ApiImplicitParams注解中,指定一个请求参数的各个方面
name:参数名
value:参数的汉字说明、解释
required:参数是否必须传
paramType:参数放在哪个地方
· header --> 请求参数的获取:@RequestHeader
· query --> 请求参数的获取:@RequestParam
· path(用于restful接口)--> 请求参数的获取:@PathVariable
· body(不常用)
· form(不常用)
dataType:参数类型,默认String,其它值dataType="Integer"
defaultValue:参数的默认值
请求头
在实际业务中,会遇到需要前端在请求头中往后端传递Token或者其他参数的需求。这里就需要进行如下的设置
@Bean//加入ioc容器
public Docket adminApiConfig(){
//需要详情配置
return new Docket(DocumentationType.SWAGGER_2)
.apiInfo(adminApiInfo())
.select()//必须有select扫描
.apis(RequestHandlerSelectors.basePackage("com.goldwind.swagger_demo.controller"))
.paths(PathSelectors.any())
.build()
.globalOperationParameters(operParameters());//设置请求头
}
// 所有接口请求添加header
private List<Parameter> operParameters(){
List<Parameter> operParameters = new ArrayList<>();
//语言
operParameters.add(new ParameterBuilder().name(HttpHeaders.ACCEPT_LANGUAGE)
.description("国际化语言(en-US-英语;zh-CN-中文)")
.modelRef(new ModelRef("string"))
.parameterType("header")
.required(false)
.build());
//token
operParameters.add(new ParameterBuilder()
.name(HttpHeaders.AUTHORIZATION)
.description("认证token")
.modelRef(new ModelRef("string"))
.parameterType("header")
.required(false)
.build());
return operParameters;
}
全局配置
@Bean//加入ioc容器
public Docket adminApiConfig(){
//需要详情配置
return new Docket(DocumentationType.SWAGGER_2)
.apiInfo(adminApiInfo())
.select()//必须有select扫描
.apis(RequestHandlerSelectors.basePackage("com.goldwind.swagger_demo.controller"))
.paths(PathSelectors.any())
.build()
.securitySchemes(Lists.newArrayList(apiKey()));//设置全局token
}
private ApiKey apiKey() {
return new ApiKey(HttpHeaders.ACCEPT_LANGUAGE , HttpHeaders.ACCEPT_LANGUAGE, "header");
}
主题
Swagger2支持不同的主题页面
- 默认
http://localhost:8080/swagger-ui.html
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger-ui</artifactId>
<version>2.9.2</version>
</dependency>
- knife4j
http://localhost:8080/doc.html
<dependency>
<groupId>com.github.xiaoymin</groupId>
<artifactId>knife4j-spring-ui</artifactId>
<version>3.0.3</version>
</dependency>
优点:
-
支持标签页
-
自定义请求头
-
导出文档
-
请求参数缓存
-
动态参数
-
…
快速开始:https://doc.xiaominfo.com/knife4j/ 参考官方文档 😀