框架简介
Swagger的作用:
自动生成强大的RESTful API文档,减少开发人员的工作量。使用Swagger,只需在代码中添加一些注解即可生成API接口文档,不需要手动编写API接口文档,这减少了开发人员的工作量。
提供API文档的同步更新:通过使用Swagger,API文档可以与代码同步更新,保持文档与实际代码的一致性,方便团队的沟通和协作。
提供API文档的可视化展示:生成的API文档页面具有良好的可视化效果,使API接口的信息更加易于理解和使用。
提供API接口的测试功能:生成的API文档页面带有测试功能,可以在文档中直接进行API接口的测试,方便开发人员进行接口调试和验证。
需要注意的是,有人认为使用Swagger与代码耦合在一起,这一点在不同的团队和项目中可能会有不同的看法。有些人认为这种方式提供了便利和一致性,而有些人则认为它可能导致代码的臃肿和维护的困难。因此,对于是否使用Swagger,应根据具体的项目需求和团队的偏好进行评估和决策。
详细步骤
pom文件中添加Swagger依赖
<!--springboot 集成 swagger-->
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger2</artifactId>
<version>2.9.2</version>
<exclusions>
<exclusion>
<groupId>io.swagger</groupId>
<artifactId>swagger-annotations</artifactId>
</exclusion>
<exclusion>
<groupId>io.swagger</groupId>
<artifactId>swagger-models</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger-ui</artifactId>
<version>2.9.2</version>
</dependency>
<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>
👆👆👆请使用以上版本依赖即可👆👆👆
👇👇👇直接使用以下版本会报错(以下依赖不用添加进pom文件),具体原因请看文章底部问题解决👇👇👇
<!-- 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>
编写Swagger的配置类
import io.swagger.annotations.ApiOperation;
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;
@EnableSwagger2 //开启对Swagger2的支持
@Configuration //声明当前类是一个配置类
public class SwaggerConfig {
//在Spring容器中配置一个Bean对象
@Bean
public Docket docket() {
//链式编程(构建器模式),基本是固定
return new Docket(DocumentationType.SWAGGER_2)
.enable(true) //设置false即关闭文档
.apiInfo(apiInfo())
.select()
//扫描带有ApiOperation注解的所有方法,为它们生成API接口文档
.apis(RequestHandlerSelectors.withMethodAnnotation(ApiOperation.class))
.paths(PathSelectors.any())
.build();
}
//创建API的基本信息,自定义即可
private ApiInfo apiInfo() {
//链式编程(构建器模式),基本是固定
return new ApiInfoBuilder()
.title("接口文档")
.description("一些内容")
.termsOfServiceUrl("https://blog.csdn.net/weixin_45966550")
.contact(new Contact("PaperFish","https://github.com/PaperFish233","PaperFish@163.com"))
.version("1.0.0")
.build();
}
}
Swagger常用注解参数
详细注解可参考官方:https://github.com/swagger-api/swagger-core/wiki/Annotations
Swagger常用注解:
@Api:用在类上,说明该类的作用;
@ApiOperation:用在方法上,说明方法的作用;
@ApiImplicitParams:用在方法上包含一组参数说明;
@ApiImplicitParam:用在@ApiImplicitParams注解中,指定一个请求参数的各个方面:
paramType:参数放在哪个地方;
header–>请求参数的获取:@RequestHeader;
query–>请求参数的获取:@RequestParam;
path–>请求参数的获取:@PathVariable (用于restful接口);
body(不常用);
form(不常用);
name:参数名;
dataType:参数类型;
required:参数是否必须传;
value:参数的意思;
defaultValue:参数的默认值;
@ApiResponses:用于表示一组响应;
@ApiResponse:用在@ApiResponses中,一般用于表达一个错误的响应信息;
code:数字,例如400;
message:信息,例如 “请求参数不合法”;
response:抛出异常的类;
@ApiIgnore:使用该注解忽略这个API,在页面上不显示;
@ApiModel:描述一个Model的信息;
@ApiModelProperty:描述一个model的属性;
swagger安全性问题: 正式上线的时候,建议关闭swagger。
在控制层需要生成API的类及方法上添加注解
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import com.neusoft.elementplusboot.po.Users;
import com.neusoft.elementplusboot.service.UsersService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiResponse;
import io.swagger.annotations.ApiResponses;
@Api(tags = "用户信息相关接口")
@RestController
@RequestMapping("/usersController")
public class UsersController {
@Autowired
UsersService usersService;
@ApiOperation(value = "分页获取所有用户信息", notes = "根据页码及页中数量获取用户信息", response = Users.class, responseContainer = "Map")
@ApiImplicitParams({
@ApiImplicitParam(paramType = "query", name = "page", value = "页码", dataType = "int", required = true),
@ApiImplicitParam(paramType = "query", name = "pageSize", value = "页中数量", dataType = "int", required = true),
@ApiImplicitParam(paramType = "query", name = "uname", value = "用户姓名", dataType = "String") })
@ApiResponses({ @ApiResponse(code = 200, message = "请求成功"), @ApiResponse(code = 201, message = "已创建新的资源"),
@ApiResponse(code = 400, message = "缺少必要的请求参数"), @ApiResponse(code = 401, message = "请求路径没有响应的权限"),
@ApiResponse(code = 403, message = "请求路径被隐藏不能访问"), @ApiResponse(code = 404, message = "请求路径没有或页面跳转路径错误"),
@ApiResponse(code = 405, message = "请求方法不支持"), })
@GetMapping("/getAllUsers")
public Map<String, Object> getAllUsers(int page, int pageSize, String uname) {
// int startpPage = (page - 1) * pageSize;
Page<Object> startPage = PageHelper.startPage(page, pageSize);
List<Users> usersList = usersService.getAllUsers(uname);
Map<String, Object> map = new HashMap<String, Object>();
map.put("list", usersList); // 记录返回内容
map.put("total", startPage.getTotal()); // 记录数据条数
return map;
}
@ApiOperation(value = "新增用户", notes = "新增用户信息")
@ApiImplicitParams({
@ApiImplicitParam(paramType = "query", name = "uid", value = "编号", dataType = "Integer", required = true),
@ApiImplicitParam(paramType = "query", name = "uname", value = "姓名", dataType = "String", required = true),
@ApiImplicitParam(paramType = "query", name = "uage", value = "年龄", dataType = "Integer", required = true),
@ApiImplicitParam(paramType = "query", name = "usex", value = "性别", dataType = "Integer", required = true) })
@ApiResponses({ @ApiResponse(code = 200, message = "请求成功"), @ApiResponse(code = 201, message = "已创建新的资源"),
@ApiResponse(code = 400, message = "缺少必要的请求参数"), @ApiResponse(code = 401, message = "请求路径没有响应的权限"),
@ApiResponse(code = 403, message = "请求路径被隐藏不能访问"), @ApiResponse(code = 404, message = "请求路径没有或页面跳转路径错误"),
@ApiResponse(code = 405, message = "请求方法不支持"), })
@PostMapping("/saveUsers")
public int saveUsers(Users users) {
return usersService.saveUsers(users);
}
@ApiOperation(value = "更新用户", notes = "更新用户信息")
@ApiImplicitParams({
@ApiImplicitParam(paramType = "query", name = "uid", value = "编号", dataType = "Integer", required = true),
@ApiImplicitParam(paramType = "query", name = "uname", value = "姓名", dataType = "String"),
@ApiImplicitParam(paramType = "query", name = "uage", value = "年龄", dataType = "Integer"),
@ApiImplicitParam(paramType = "query", name = "usex", value = "性别", dataType = "Integer") })
@ApiResponses({ @ApiResponse(code = 200, message = "请求成功"), @ApiResponse(code = 201, message = "已创建新的资源"),
@ApiResponse(code = 400, message = "缺少必要的请求参数"), @ApiResponse(code = 401, message = "请求路径没有响应的权限"),
@ApiResponse(code = 403, message = "请求路径被隐藏不能访问"), @ApiResponse(code = 404, message = "请求路径没有或页面跳转路径错误"),
@ApiResponse(code = 405, message = "请求方法不支持"), })
@PutMapping("/updateUsers")
public int updateUsers(Users users) {
return usersService.updateUsers(users);
}
@ApiOperation(value = "删除用户", notes = "删除用户信息")
@ApiImplicitParams({
@ApiImplicitParam(paramType = "query", name = "uid", value = "编号", dataType = "Integer", required = true) })
@ApiResponses({ @ApiResponse(code = 200, message = "请求成功"), @ApiResponse(code = 201, message = "已创建新的资源"),
@ApiResponse(code = 400, message = "缺少必要的请求参数"), @ApiResponse(code = 401, message = "请求路径没有响应的权限"),
@ApiResponse(code = 403, message = "请求路径被隐藏不能访问"), @ApiResponse(code = 404, message = "请求路径没有或页面跳转路径错误"),
@ApiResponse(code = 405, message = "请求方法不支持"), })
@DeleteMapping("/deleteUsers")
public int deleteUsers(Integer uid) {
return usersService.deleteUsers(uid);
}
}
问题解决
报错Failed to start bean ‘documentationPluginsBootstrapper’
报错可能原因:SpringBoot版本和Swagger版本不匹配导致(Springfox使用的路径匹配是基于AntPathMatcher的,而Spring Boot 2.6.X使用的则是PathPatternMatcher)
解决方法:
1、修改SpringBoot的版本,使用早期版本;
2、yml配置文件中添加如下配置(设置"ant_path_matcher"作为匹配策略):
spring:
mvc:
pathmatch:
matching-strategy: ant_path_matcher
报错java.lang.NumberFormatException: For input string: “”
报错可能原因:@ApiImplicitParams注解属性中的参数类型出了问题,空字符串""无法转成Number。(swagger版本的问题,之前使用的是io.springfox:springfox-swagger2:2.9.2的版本,而该版本依赖了swagger-models的1.5.20版本(会导致报此错),深挖原因是1.5.20版本中的example只判断了是否为null,没有判断是否为空串;1.5.21版本对两者都进行了判断。)
解决方法:
1、在注解中为int属性的参数添加一个默认值属性(example = “1”):
@ApiImplicitParams(@ApiImplicitParam(name = "id",value = "编号",dataType = "int",required = true,example = "1"))
2、排除springfox-swagger2中的swagger-models依赖,导入io.swagger:swagger-models的1.5.21版本。将之前导入pom文件的两个依赖换成如下即可:
<!--springboot 集成 swagger-->
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger2</artifactId>
<version>2.9.2</version>
<exclusions>
<exclusion>
<groupId>io.swagger</groupId>
<artifactId>swagger-annotations</artifactId>
</exclusion>
<exclusion>
<groupId>io.swagger</groupId>
<artifactId>swagger-models</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger-ui</artifactId>
<version>2.9.2</version>
</dependency>
<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>
结语
仅自学留档以及整合,部分内容参考自:
http://t.csdn.cn/N8dr1 | http://t.csdn.cn/jSgPP | http://t.csdn.cn/OAIN9