springboot swagger
1. 介绍
目前大部分项目都是前后端分离,或者是以服务的形式暴露RESTful API接口,但是如何向调用方提供接口说明文档?如何快速单元测试我们的接口?如何在更改了接口之后快速的更新于接口文档中?带着这些问题,引入swagger。
特性:
- swagger可以生成互动性的API控制台
- 调用者和开发者尝试API
- 形成一种合作契约,让团队更加敏捷的开发
- 对代码有一定的入侵型
2. 集成
2.1 POM配置
pom中增加swagger的依赖
io.springfox
springfox-swagger-ui
2.4.0
io.springfox
springfox-swagger2
2.4.0
2.2 开启swagger
在入口程序的启动类(Application.java)上增加@EnableSwagger2的注解
@EnableSwagger2
@SpringBootApplication
public class Application {
public static void main(String[] args) {
//启动入口
SpringApplication.run(Application.class, args);
}
}
2.3 配置swagger
@Configuration
public class AppConfig {
/**
* 创建swagger ui的摘要
* @return
*/
@Bean
public Docket docket() {
return new Docket(DocumentationType.SWAGGER_2)
.apiInfo(apiInfo())
.select()
// 扫描的class的包路径
.apis(RequestHandlerSelectors.basePackage("pers.mateng.demo.springboot"))
// 只扫描类上有API注解的class
// .apis(RequestHandlerSelectors.withClassAnnotation(Api.class))
// 只扫描方法上有ApiOperation注解的方法
// .apis(RequestHandlerSelectors.withMethodAnnotation(ApiOperation.class))
.paths(PathSelectors.any())
.build();
}
/**
* swagger ui的标题信息
* @return
*/
private ApiInfo apiInfo() {
return new ApiInfoBuilder()
.title("标题")
.description("副标题")
.version("1.0")
.build();
}
}
2.4 声明 API
修改UserController,注意类注解(@Api)和方法注解(@ApiOperation)
@RestController
@RequestMapping(path="user")
@Api(tags="用户管理")
public class UserController {
@Autowired
private UserDao userDao;
@ApiOperation(value="查询用户", notes="测试无请求参数的swagger-ui")
@RequestMapping(method=RequestMethod.GET)
public List findAll() {
return userDao.findAll();
}
@ApiOperation(value="增加用户-测试1", notes="测试application/x-www-form-urlencoded形式提交参数")
@RequestMapping(method=RequestMethod.POST)
public User add(@ModelAttribute User user) {
return userDao.save(user);
}
@ApiOperation(value="修改用户-测试1", notes="测试application/json形式提交参数")
@RequestMapping(path="/{id}", method=RequestMethod.PUT)
public User update1(@ApiParam(value="用户id") @PathVariable Long id, @RequestBody User user) {
User temp = userDao.findOne(id);
if(temp != null) {
temp.setName(user.getName());
temp.setAge(user.getAge());
return userDao.save(temp);
}
return null;
}
@ApiOperation(value="根据id查询用户", notes="测试path参数提交")
@GetMapping(path="/{id}")
public User findById(@ApiParam(value="用户id") @PathVariable Long id) {
return userDao.findOne(id);
}
@ApiOperation(value="根据id删除用户", notes="测试path参数提交")
@DeleteMapping(path="/{id}")
public Boolean del(@ApiParam(value="用户id") @PathVariable Long id) {
userDao.delete(id);
return Boolean.TRUE;
}
}
3. 验证
启动工程,使用eclipse的run as重新启动Application的main函数
使用浏览器访问http://localhost:8888/swagger-ui.html。即可查看UserControlerl中暴漏的接口
填写参数后,点击 “try it out” 即可发送请求
4. 进阶详解
4.1 @ModelAttribute 的参数说明
在swagger-ui上查看“增加用户-测试1”接口,发现该接口的描述并不完善,问题如下:
- 所有的请求参数都没有中文描述
- 增加用户时参数“id”是不需要的
那么接口调用方是无法更好的理解接口的使用,解决办法如下
方法一
- 使用 @ApiIgnore,让 swagger 忽略该实体类的参数
- 使用 @ApiImplicitParams 重新声明参数的类型、说明、是否必须、参数位置
详细代码如下:
@ApiOperation(value="增加用户-测试2")
@RequestMapping(path="add2", method=RequestMethod.POST)
@ApiImplicitParams({
@ApiImplicitParam(value="用户名", name="name", required=true, dataType="String", paramType="form"),
@ApiImplicitParam(value="年龄", name="age", required=false, dataType="integer", paramType="form")
})
public User add2(@ApiIgnore @ModelAttribute User user) {
return userDao.save(user);
}
方法二
- 升级 swagger的版本到2.7.0
- 使用 @ApiModelProperty(hidden=true) 隐藏参数
- 使用 @ApiModelProperty(value = "xxx") 描述参数的说明
- 使用 @ApiModelProperty(required=false) 标识参数是否必须输入
修改实体类User,==注意每个属性的注解==
@Entity
@Table(name="TB_USER")
public class User {
@Id
@GeneratedValue(strategy=GenerationType.AUTO)
@Column(name="U_ID")
@ApiModelProperty(hidden=true)
private Long id;
@Column(name="U_NAME", nullable = false, length=32, unique=true)
@ApiModelProperty(value = "用户名称", required=true)
private String name;
@Column(name="U_AGE", length=4)
@ApiModelProperty(value = "年龄", required=false)
private Integer age;
get/set...
}
4.2 @RequestBody 的参数说明
在 swagger-ui 上查看“修改用户-测试1”接口,发现该接口的描述并不完善,问题如下:
- 所有的请求参数都没有中文描述
- 为了追求 RESTful 风格,导致id声明了两次,在 Path 和 Resquestbody 中各声明了一次
所以接口调用方是无法更好的理解接口的使用,解决办法如下
方法一
不使用@Resquestbody 直接使用@ModelAttribute + @ApiImplicitParams的方法,==也就是4.1章节中的方法一==
代码如下:
@ApiOperation(value="修改用户-测试2", notes="测试application/x-www-form-urlencoded形式提交参数")
@RequestMapping(path="update2", method=RequestMethod.PUT)
@ApiImplicitParams({
@ApiImplicitParam(value="用户id", name="id", required=true, dataType="Integer", paramType="form"),
@ApiImplicitParam(value="用户名", name="name", required=true, dataType="String", paramType="form"),
@ApiImplicitParam(value="年龄", name="age", required=false, dataType="integer", paramType="form")
})
public User update2(@ApiIgnore @ModelAttribute User user) {
User temp = userDao.findOne(user.getId());
if(temp != null) {
temp.setName(user.getName());
temp.setAge(user.getAge());
return userDao.save(temp);
}
return null;
}
方法二
==也就是4.1章节中的方法二==
- 使用 @ApiModelProperty(hidden=true) 隐藏参数
- 使用 @ApiModelProperty(value = "xxx") 描述参数的说明
- 使用 @ApiModelProperty(required=false) 标识参数是否必须输入
在实体类 User上增加注解,代码如下:
@Entity
@Table(name="TB_USER")
public class User {
@Id
@GeneratedValue(strategy=GenerationType.AUTO)
@Column(name="U_ID")
@ApiModelProperty(hidden=true)
private Long id;
@Column(name="U_NAME", nullable = false, length=32, unique=true)
@ApiModelProperty(value = "用户名称", required=true)
private String name;
@Column(name="U_AGE", length=4)
@ApiModelProperty(value = "年龄", required=false)
private Integer age;
get/set……
}
4.3 @PathVariable/@RequestParam 的参数说明
在这两个注解的前面增加swagger的注解@ApiParam(value="xxx")
@DeleteMapping(path="/{id}")
public Boolean del(@ApiParam(value="用户id") @PathVariable Long id) {
userDao.delete(id);
return Boolean.TRUE;
}
@GetMapping(path="/name")
public String findByName(@ApiParam(value="用户名") @RequestParam String name) {
return name;
}
4.4 总结
在4.1章节和4.2章节中,处理参数的说明都使用了两种方法,概括的讲,方法一是在方法体的注解上想办法解决,方法二是在参数的属性上想办法解决。
方法一的优缺点分析:
- 缺点:写的代码多。
- 优点:适应性好,例如:有多个api接口都需要使用同一个javabean作为入参,但是每个接口实际暴露的参数不一样。就可以复用同一个javabean,而在各自的方法上处理。
- 优点:对javabean没有入侵性。
- 适合formdata/x-www-form-urlencoded表单提交。
方法二的优缺点:
- 缺点:复用性差,例如:有多个api接口都需要使用同一个javabean作为入参,但是每个接口实际暴露的参数不一样。不能复用同一个javabean。
- 缺点:如果一个javabean即作为入参,又作为出参。
- 优点:代码写的少。
- 适合application/json提交参数。
5. 源码
springboot-demo-3