本文注重实践,理论介绍可自行google。本文将从Swagger2的集成开始,逐步完成一个具有高度参考价值的API文档。
//Swagger
implementation 'io.springfox:springfox-swagger2:2.9.2'
implementation 'io.springfox:springfox-swagger-ui:2.9.2'
//另外项目中会用到lombok所以这里也引入依赖
//lombok插件,这里采用官方推荐的方式,防止gradle build时找不到lombok
annotationProcessor 'org.projectlombok:lombok:1.18.2'
compileOnly 'org.projectlombok:lombok:1.18.2'
testAnnotationProcessor 'org.projectlombok:lombok:1.18.2'
testCompileOnly 'org.projectlombok:lombok:1.18.2'
@EnableSwagger2
,启用swagger2 @Configuration
public class Swagger2Config {
@Bean
public Docket adminsApi() {
return new Docket(DocumentationType.SWAGGER_2)
.apiInfo(apiInfo())
.select()
.apis(RequestHandlerSelectors.basePackage("org.virtuex"))
.build()
.groupName("apis")
;
}
private ApiInfo apiInfo(){
return new ApiInfoBuilder()
.title("xxxx系统接口说明")
.description("测试使用")
.version("v1.0")
.build();
}
}
这里随便写个controller来测试下页面显示的效果,具体代码不贴了,可在最后的github仓库上查看,访问http://127.0.0.1:8880/swagger-ui.html
效果如下:
这里可以看到系统的接口,代码中写了两个controller,如下:
@Api("认证与授权")
@RestController
public class AuthController {
@RestController
@ApiIgnore
public class UserController {
第二个使用了@ApiIgnore
,这个注解会跳过这个controller。所以页面上没有显示。
但是这只是简单的接口名称以及一些状态码,参考价值并不大,下面将就这些接口细化下显示的内容,使其具有更大的参考价值。
一份具有高度参考价值的文档,必须要有直观、详细的描述。其中需要描述接口的作用,描述输入输出参数的作用等,下面就此进行完善
@Api
注解为类添加说明@RestController
@Api("用户管理")
public class UserController {
@ApiOperation
给方法添加描述 @ApiOperation("添加用户")
@PostMapping("/add")
public String addAdmin(@RequestBody User user){
return "OK";
}
}
User
类定义如下:@Data
@Component
@ApiModel(value = "User", description = "用户实体类")
public class User implements Serializable {
private static final long serialVersionUID = 1L;
@ApiModelProperty(value = "用户ID")
private Integer userId;
@ApiModelProperty(value = "用户名" , example = "张三")
private int username;
@ApiModelProperty(value = "密码")
private String password;
}
这里需要注意的是:
- Model与Swagger集成需要在对应的controller中加入@RequestBody注解,否则Swagger不显示Model且不报错
- 如果结合lombok需要有@ Data注解(否则就要有getter/setter),否则swagger上不显示字段信
以新增用户的相应为例,新增下面的model作为相应响应结构:
@Data
@ApiModel(value = "AddDataResponse", description = "响应实体")
public class AddDataResponse {
@ApiModelProperty(value = "数据主键值" , example = "1")
private Integer dataRid;
@ApiModelProperty(value = "响应状态码" , example = "200")
private Integer code;
@ApiModelProperty(value = "描述" , example = "创建成功")
private String desc;
}
在对应的controller方法上配置响应结构:
@ApiOperation("添加用户")
@PostMapping("/add")
@ApiResponses({@ApiResponse(code = 200, response = AddDataResponse.class, message = "成功")})
public String addAdmin(@RequestBody User user){
return "OK";
}
启动项目,进入swagger-ui页面
从图中可以看出,新增的响应内容显示在了页面上。
从上一例中看出,可以指定多个响应,并且每个状态码都有具体的响应结构。接下来就以200,401,403为例来进行封装。
@Data
@ApiModel(value = "Response401", description = "401响应实体")
public class Response401 {
@ApiModelProperty(value = "业务ID" , example = "12345678")
private Long bizId;
@ApiModelProperty(value = "描述" , example = "未认证")
private String message;
@ApiModelProperty(value = "建议" , example = "请先认证")
private String suggestion;
}
@Data
@ApiModel(value = "Response403", description = "403响应实体")
public class Response403 {
@ApiModelProperty(value = "业务ID" , example = "123564")
private Long bizId;
@ApiModelProperty(value = "描述" , example = "禁止访问")
private String message;
@ApiModelProperty(value = "建议" , example = "请确认是否有权限访问")
private String suggestion;
}
@ApiOperation("添加用户")
@PostMapping("/add")
@ApiResponses({@ApiResponse(code = 200, response = AddDataResponse.class, message = "成功"),
@ApiResponse(code = 401, response = Response401.class, message = "未认证"),
@ApiResponse(code = 403, response = Response403.class, message = "禁止访问")
})
public String addAdmin(@RequestBody User user){
return "OK";
}
根据前几例中的响应Model,每个响应都有一个业务ID,所以这个Id我们可以抽象出一个BaseModel
@Data
public abstract class BaseModel {
@ApiModelProperty(value = "业务流水号" , example = "123-454-845-454")
private String bizId;
}
其他Model继承自此Model
public class Response401 extends BaseModel {
@ApiModelProperty(value = "描述" , example = "未认证")
private String message;
@ApiModelProperty(value = "建议" , example = "请先认证")
private String suggestion;
}
实例中只有一个Controller,所以在页面显示布局不会很拥挤。一旦controller多了,全挤在一个页面,那就显得很乱。这时可以通过新建Docket来指定分组。如,增加Oauth和自定义的auth两个接口组
@Bean
public Docket authApi() {
return new Docket(DocumentationType.SWAGGER_2)
.apiInfo(apiInfo())
.select()
.apis(RequestHandlerSelectors.any())
.paths(PathSelectors.ant("/auth/**"))
.build()
.groupName("auth_api")
;
}
@Bean
public Docket oauthApi() {
return new Docket(DocumentationType.SWAGGER_2)
.select()
.apis(RequestHandlerSelectors.any())
.paths(PathSelectors.ant("/oauth/**"))
.build()
.groupName("oauth_api")
;
}
github地址