您的位置:首页 > 编程语言 > Java开发

SpringBoot如何优雅的使用Swagger

2017-12-30 22:46 776 查看
可以参考我的github项目kingboy-springboot-web,包含详细的演示和说明以及其它相关技术。

一、Swagger为什么会出现?

在以前,我们项目开发的流程往往是这样的:

产品把前后端人员叫过来开会:我们的需求是这样的,balabala。然后前端拿着原型页面开始画前台UI,后端看着需求文档开始写接口。

后端写完一个接口,肯定需要测试一下写的对不对,那么经常有这样一个过程:

- 打开一个模拟http请求工具,例如postMan
- 填写接口的请求地址
- 如果是post带body的请求,还要拼接一长串的json字符串,哪怕错一个字符都不行
- 请求后台接口


当前后台开发完成时,前后端两个人开始联调,往往会出现以下情景:

对话一:

- 前端:你这手机字段名怎么叫phone?我的叫phoneNumber
- 后端:??!!
- 前端:不行,就你改


对话二:

- 前端:你这接口怎么调不通?
- 后端:额,我看看 ………2 minutes later……… 我接口文档忘记更新了,接口格式已经改了,所以调不通
- 前端:...


对话三:

- 前端:你这个接口里的id传的是用户id还是订单id?
- 后端:等会,我看看……………2 minutes later………………
- 后端:再等会,我代码里注释忘记同步修改了,我查下数据库…………


以上的情景时常发生,究其原因是因为前后端不能很好的同步信息,既耽误时间,又消耗精力,而我们关注的核心应该是代码。

在联调前,开发人员还要写接口文档(一种令人蛋疼的东西),当代码改动时,一般也要同步修改接口文档(然而……)。

那么有没有那么一个工具可以帮我们去做这些事呢?可不可以让我们只关注我们的代码书写呢?肯定是有的,那就是Swagger。

二、Swagger解决了什么问题?

Swagger会自动根据我们的接口来生成一个html页面,在这个页面上我们可以看到所有接口信息,信息中包含了有哪些参数,每个参数代表什么意思,如果是一个带body体的请求,还会自动帮我们生成json格式的bogy。并且还可以像http请求工具那样进行接口请求,示例如下。

接口代码:

@ApiOperation(value = "更新用户", notes = "更新用户,ID必传")
@PutMapping
public ApiResult updateUser(@RequestBody UserDTO userDTO) {
return ApiResult.success("success");
}

@DeleteMapping("/{id}")
public ApiResult removeUser(@ApiParam(value = "用户ID") @PathVariable(value = "id")  Integer id,
@ApiParam(value = "用户名") @RequestParam String username) {
return ApiResult.success("success");
}


生成的html页面





三、SpringBoot集成Swagger的环境准备

1.引入依赖

//spring mvc
'org.springframework.boot:spring-boot-starter-web',
"com.fasterxml.jackson.datatype:jackson-datatype-jsr310",
//swagger
"io.springfox:springfox-swagger2:$swaggerVersion",
"io.springfox:springfox-swagger-ui:$swaggerVersion",


2.Swagger配置

我们写一个Swagger的配置类如下:

/**
* @author kingboy--KingBoyWorld@163.com
* @date 2017/12/30 下午7:30
* @desc Swagger配置类.
*/

@EnableSwagger2//Swagger的开关,表示我们在项目中启用Swagger
@Configuration//声名这是一个配置类
@ConfigurationProperties(prefix = "swagger")//SpringBoot中提供的属性自动赋值。也可以直接在属性上使用@Value("${swagger.属性名}")进行赋值
public class SwaggerConfiguration {

//controller接口所在的包
private String basePackage = "com.kingboy.controller";

//当前文档的标题
private String title = "他很懒,什么都没有留下";

//当前文档的详细描述
private String description = "他很懒,什么都没有留下";

//当前文档的版本
private String version = "V1.0";

@Bean
public Docket createRestApi() {
return new Docket(DocumentationType.SWAGGER_2)
.apiInfo(apiInfo())
.select()
.apis(RequestHandlerSelectors.basePackage(basePackage))
.paths(PathSelectors.any())
.build();
}

private ApiInfo apiInfo() {
return new ApiInfoBuilder()
.title(title)
.description(description)
.version(version)
.build();
}

//Setter Getter ...

}


3.配置文件,这里使用yml文件进行配置

resources/application.yml

swagger:
basePackage: com.kingboy.controller
title: 用户服务
description: 用户基本增删改查
version: V1.0


四、Swagger的使用方法

Swagger的使用注解有很多,这里我们只讲最常用的注解,以及这些注解中最常用的属性。

@Api(value = “用户Controller”)

加在controller类上

value表示该类的描述

然而我发现加不加,在swagger的页面上没有任何的体现,所以我并没有加

@ApiOperation(value = “获取用户信息”, notes = “通过id获取用户”)

加在相应的请求处理方法上

value表示该方法的说明

note相当于对该方法的详细说明,也就是更加完整的描述

@ApiParam(value = “用户ID”)

加在请求方法的普通参数上

value的值是对该参数的说明

需要注意的是,@RequestParam注解不能省略,否则Swagger会当做body进行解析。

@ApiModel(value = “用户信息”)

加在请求方法的请求对象的类上

例如有一个请求方法saveUser(User user), 则需要加在User这个类上面(可以参照下面的示例)

@ApiModelProperty(value = “用户ID”, example = “1”)

加在请求方法的参数对象的属性上

value 对该属性的描述

example 代表swagger文档中自动生成的json的默认值

@ApiImplicitParams(value = {})

用在请求方法上

这个注解必须和下面的@ApiImplicitParam配合使用

当请求方法中的请求参数很多的时候,例如saveUser(String username, Integer age, Date birthday, String phone),这个时候我们如果还是使用@ApiParam会让方法体变的非常乱。

@ApiImplicitParam(name = “id”, paramType = “path”, value = “用户ID”)

用在@ApiImplicitParams的value中

name 参数中属性的名字

paramType 这个参数必须指定,代表参数的传输类型,有五个取值:path(url参数),query(请求参数), body(请求体参数),header(头部参数),form(表单参数)。

value 对这个属性的描述

再此强调一下,paramType不能少,paramType不能少,paramType不能少

下面直接看示例:

UserController

/**
* @author kingboy--KingBoyWorld@163.com
* @date 2017/11/26 下午1:20
* @desc 用户接口服务.
*/
@RestController
@RequestMapping(value = "/user")
public class UserController {

@ApiOperation(value = "获取用户信息", notes = "通过id获取用户")
@GetMapping(value = "/{id}")
@ApiImplicitParams(value = {
@ApiImplicitParam(name = "id", paramType = "path", value = "用户ID"),
@ApiImplicitParam(name = "username", paramType = "query", value = "用户名")
})
public ApiResult getUser(@PathVariable(value = "id") Integer id, @RequestParam String username) {
return ApiResult.success(new UserDTO(id, username, LocalDateTime.now()));
}

@ApiOperation(value = "保存用户", notes = "保存用户,ID为后台自动生成")
@PostMapping
public ApiResult saveUser(@RequestBody UserDTO userDTO) {
return ApiResult.success(userDTO);
}

@ApiOperation(value = "更新用户", notes = "更新用户,ID必传")
@PutMapping
public ApiResult updateUser(@RequestBody UserDTO userDTO) {
return ApiResult.success("success");
}

@DeleteMapping("/{id}")
public ApiResult removeUser(@ApiParam(value = "用户ID") @PathVariable(value = "id")  Integer id,
@ApiParam(value = "用户名") @RequestParam String username) {
return ApiResult.success("success");
}

}


UserDTO

@Data
@ApiModel(value = "用户信息")
@NoArgsConstructor
@AllArgsConstructor
public class UserDTO {

@ApiModelProperty(value = "用户ID", example = "1")
private Integer id;

@ApiModelProperty(value = "用户名", example = "king")
private String username;

@ApiModelProperty(value = "生日", example = "1999-12-31 12:59")
@JsonFormat(pattern = "yyyy-MM-dd HH:mm")
private LocalDateTime birthday;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: