文章目录
Swagger3.0快速入门
学习Swagger所需要注意的前提
我们在使用Swagger的时候需要对比SpringBoot的版本和Swagger版本是否兼容,不然启动时会运行时错误。
SpringBoot 2.56 版本需要使用 Swagger2.xx版本
SpringBoot 2.7.xx版本需要使用 Swagger3.0版本
如果SpringBoot可以正常启动,但是输入Swagger默认地址报405,说明Swagger配置类的注解有问题或者在yml文件中没有配置:
spring:
mvc:
pathmatch:
matching-strategy: ANT_PATH_MATCHER
1 Swagger快速入门
前后端分离时代,随之而来的是无法及时协商的问题,包括前端能够及时看懂这些API,这时Swagger应运而生
1.1 Swagger引入
Swagger 号称历史上最流行的API框架,Swagger2.xx与Swagger3.0相比还是有很大的不同。
- 应用主类添加注解@EnableOpenApi (Swagger2是@EnableSwagger2)
- Swagger配置类SwaggerProperties.class,与swagger2.xx 版本有差异
- 自定义一个配置类 SwaggerConfiguration.class
- 访问地址:
Swagger3.0: http://localhost:8080/swagger-ui/index.html
Swagger2.xx: http://localhost:8080/swagger-ui.html
1.2 Swagger3.0使用教程
1.21 导入依赖
Maven项目中引入springfox-boot-starter依赖:
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-boot-starter</artifactId>
<version>3.0.0</version>
</dependency>
1.22 application.yml配置
spring:
application:
name: springfox-swagger
server:
port: 8080
# ===== 自定义swagger配置 ===== #
swagger:
enable: true
application-name: ${spring.application.name}
application-version: 1.0
application-description: springfox swagger 3.0整合Demo
try-host: http://localhost:${server.port}
1.23.修改默认API文档显示页面
@Bean
public Docket docket() {
// 配置Swagger的Docket的bean实例
return new Docket(DocumentationType.SWAGGER_2)
.apiInfo(apiInfo())//配置Swagger信息
// .enable(false)//是否启动swagger,如果为false,那么浏览器无法访问swagger
.groupName("帝天xxx有限公司")
.select()
/**
* apis():指定扫描的接口
* RequestHandlerSelectors:配置要扫描接口的方式
* basePackage:指定要扫描的包
* any:扫面全部
* none:不扫描
* withClassAnnotation:扫描类上的注解(参数是类上注解的class对象)
* withMethodAnnotation:扫描方法上的注解(参数是方法上的注解的class对象)
*/
.apis(RequestHandlerSelectors.basePackage("com.cdy.studydemo1.controller"))
/**
* paths():过滤路径
* PathSelectors:配置过滤的路径
* any:过滤全部路径
* none:不过滤路径
* ant:过滤指定路径:按照按照Spring的AntPathMatcher提供的match方法进行匹配
* regex:过滤指定路径:按照String的matches方法进行匹配
*/
.paths(PathSelectors.any())
.build();
}
@Bean
public Docket docket2(){
return new Docket(DocumentationType.SWAGGER_2).groupName("大忽悠2号");
}
//配置Swagger信息
/*
String title,
String description,
String version,
String termsOfServiceUrl,
Contact contact,
String license,
String licenseUrl,
Collection<VendorExtension> vendorExtensions
*/
private ApiInfo apiInfo(){
return new ApiInfo(
"在线接口文档",
"这是关于项目的接口文档",
"1.0",
"http://t.csdn.cn/2kz6N",
new Contact("cdy", "http://t.csdn.cn/2kz6N","164893xxx0811@qq.com"),
"Apache 2.0",
"http://www.apache.org/licenses/LICENSE-2.0",
new ArrayList<VendorExtension>());
}
1.24 Swagger使用场景
首先要判断是不是开发环境,可以设置一个flag表示用来表示:flag=1即表示生产环境
然后将flag的值传给enable(flag)
首先在resources目录下新建两种springboot配置文件
开发环境:application-dev.properties
server.port=8081
正式环境:application-pro.properties
server.port=8082
然后在主配置文件application.properties中激活开发环境
spring.profiles.active=dev
然后我们到SwaggerConfig中的docket()方法中添加代码:
首先给该方法传一个参数Environment的实例
Environment environment
首先设置要配置的Swagger环境:这里可以添加多个环境
Profiles.of("dev", "test");
然后通过environment.acceptsProfiles方法判断是否处在上一步设定的dev/test环境中,返回一个boolean的值,我们用flag接收
boolean flag = environment.acceptsProfiles(profiles);
然后修改enable中的参数为flag,即通过flag来判断是否开启Swagger
.enable(flag)//通过flag判断是否开启
1.25 配置API文档分组
1. 设置默认组名
可以看到,我们默认只有一个组且组名为default
我们可以在docket通过.groupName中设置组名
2. 配置多个组
上述我们成功修改了组名,但是只有一个组,如果我们想要多个组呢?
观察代码可以知道,一个Docket实例就对应着一个组,因此我们配置多个docket就对应着多个组
1.26 配置Model实体类
只要我们的controoler层方法中,返回值中存在实体类,他就会被扫描到Swagger中
@RestController
@RequestMapping("/difficult")
@Api(tags = "Difficult数据交互")
public class DifficultController {
@Autowired
private DifficultService difficultService;
@GetMapping("/getquestionid/{questionId}")
@ApiOperation(value = "通过问题id查找题目详情实体")
public Difficult getDiff(@PathVariable@ApiParam(value="问题编号参数") String questionId){
Difficult diff = difficultService.getDiff(questionId);
return diff;
}
@ApiOperation(value= "测试接口是否有问题")
@GetMapping("/test")
public Difficult testmethod(){
Difficult difficult = new Difficult(6,"6","easy");
return difficult;
}
}
现在的问题是,页面显示出来的返回的Difficult类,如果是非常复杂的情况下,没有注释就很难看懂,这样就有了注解来进行解释
@ApiModel为类添加注释
@ApiModelProperty为类属性添加注释
package com.cdy.studydemo1.entity;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
@ApiModel(value = "题目详情类,主要描述题目的难度")
public class Difficult {
@ApiModelProperty(value="题目详情表唯一标识")
private int id;
@ApiModelProperty(value = "题目id")
private String questionId;
@ApiModelProperty(value = "题目难度")
private String difficultLevel;
public Difficult() {
}
public Difficult(int id, String questionId, String difficultLevel) {
this.id = id;
this.questionId = questionId;
this.difficultLevel = difficultLevel;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getQuestionId() {
return questionId;
}
public void setQuestionId(String questionId) {
this.questionId = questionId;
}
public String getDifficultLevel() {
return difficultLevel;
}
public void setDifficultLevel(String difficultLevel) {
this.difficultLevel = difficultLevel;
}
@Override
public String toString() {
return "Difficult{" +
"id=" + id +
", questionId=" + questionId +
", difficultLevel='" + difficultLevel + '\'' +
'}';
}
}
1.27 Swagger常用注解总结
// @Api: 修饰整个类,描述Controller的作用
@Api(value = "注册登陆", tags = "注册登陆相关接口")
// @ApiOperation: 描述一个类的一个方法,或者说一个接口
@ApiOperation(value = "用户注册", notes = "用户注册", httpMethod = "POST")
@ApiParam // 单个参数描述
// @ApiModel: 用对象来接收参数
@ApiModel(value = "用户对象BO", description = "用户从客户端传入的数据的封装")
// @ApiModelProperty: 用对象接收参数时,描述对象的一个字段
@ApiModelProperty(value = "用户名", name = "username", example = "Orcas", required = true)
@ApiResponse // HTTP响应其中1个描述
@ApiResponses // HTTP响应整体描述
@ApiIgnore // 使用该注解忽略这个API
@ApiError // 发生错误返回的信息
@ApiImplicitParam // 一个请求参数
@ApiImplicitParams // 多个请求参数
=》 @ApiImplicitParams({
@ApiImplicitParam(name = "page", value = "页码", required = true, paramType = "path", dataType = "int"),
@ApiImplicitParam(name = "size", value = "每页记录数", required = true, paramType = "path", dataType = "int")})
对上述的说明
@Api:用在请求的类上,表示对类的说明
tags="说明该类的作用,可以在UI界面上看到的注解"
value="该参数没什么意义,在UI界面上也看到,所以不需要配置"
@ApiOperation:用在请求的方法上,说明方法的用途、作用
value="说明方法的用途、作用"
notes="方法的备注说明"
@ApiImplicitParams:用在请求的方法上,表示一组参数说明
@ApiImplicitParam:用在@ApiImplicitParams注解中,指定一个请求参数的各个方面
name:参数名
value:参数的汉字说明、解释
required:参数是否必须传
paramType:参数放在哪个地方
· header --> 请求参数的获取:@RequestHeader
· query --> 请求参数的获取:@RequestParam
· path(用于restful接口)--> 请求参数的获取:@PathVariable
· body(不常用)
· form(不常用)
dataType:参数类型,默认String,其它值dataType="Integer"
defaultValue:参数的默认值
@ApiResponses:用在请求的方法上,表示一组响应
@ApiResponse:用在@ApiResponses中,一般用于表达一个错误的响应信息
code:数字,例如400
message:信息,例如"请求参数没填好"
response:抛出异常的类
@ApiModel:用于响应类上,表示一个返回响应数据的信息
(这种一般用在post创建的时候,使用@RequestBody这样的场景,
请求参数无法使用@ApiImplicitParam注解进行描述的时候)
@ApiModelProperty:用在属性上,描述响应类的属性
总结: 发布的时候,记得关闭Swagger,可以通过生产环境设置来完成这一需求
swagger 3.0的swagger页面访问url
https://ip:port或域名/设置的请求前缀/swagger-ui/index.html#/
2 Swagger3增强插件—knife4j
2.1导入依赖
<dependency>
<groupId>com.github.xiaoymin</groupId>
<artifactId>knife4j-spring-boot-starter</artifactId>
<version>3.0.2</version>
</dependency>
启动knife4j
在上面配置Swagger的Swagger3Config中添加@EnableKnife4j注解,该注解可以开启knife4j的增强功能。
@EnableKnife4j
@Configuration
@EnableOpenApi
public class Swagger3Config {
// ...
}
此时,如果依旧访问http://localhost:8080/swagger-ui/index.html会发现显示并没有变化。这里我们需要访问http://localhost:8088/doc.html。
2.2 Swagger3.0 异常:导致NumberFormatException
原因:
查看源码得知,源码中只判断了examole==null,忽略了""空字符串的情况!
解决方案:
<!--指定swagger-models版本,解决报错-->
<dependency>
<groupId>io.swagger</groupId>
<artifactId>swagger-annotations</artifactId>
<version>1.5.21</version>
</dependency>
<dependency>
<groupId>io.swagger</groupId>
<artifactId>swagger-models</artifactId>
<version>1.5.21</version>
</dependency>
2.3 总结使用Swagger的增强插件要导入的依赖
<!--swagger-->
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-boot-starter</artifactId>
<version>3.0.0</version>
</dependency>
<!-- swagger ui-->
<dependency>
<groupId>com.github.xiaoymin</groupId>
<artifactId>knife4j-spring-boot-starter</artifactId>
<version>3.0.2</version>
</dependency>
<!--指定swagger-models版本,解决报错-->
<dependency>
<groupId>io.swagger</groupId>
<artifactId>swagger-annotations</artifactId>
<version>1.5.21</version>
</dependency>
<dependency>
<groupId>io.swagger</groupId>
<artifactId>swagger-models</artifactId>
<version>1.5.21</version>
</dependency>
3 致谢
参考文章「Binary Oracle」的原创文章,原文链接