写在前面
众所周知规范的HTTP接口由请求方式、请求参数、请求地址、响应数据、统一异常拦截构成。所以本文从这五个方面入手,规范接口,减少前后端联调时间!本文基于REST的风格规范后端接口,对REST的说明可以参考这篇文章:www.ruanyifeng.com/blog/2011/0…
请求方式
使用HTTP的请求方式代表操作资源的动作,定义接口时要根据业务选择适合的请求方式,常见的HTTP请求有5种:
1. GET: 从服务器查询出一个或多个数据
2. PUT: 更新服务器完整资源
3. PATCH: 更新服务器部分资源
4. POST: 新增资源
5. DELETE: 删除资源
请求地址
请求地址就是URL,我们已经用HTTP请求代表操作资源的动作了,所以我们在URL中就不应该出现动作。
假设场景设计一个接口操作公司的部门和员工,下面给出规范的URL的例子:
查询示例
1. 查询所有部门
GET /department
2. 根据部门编号查询部门信息
GET /department/{id}
3. 根据部门编号,员工编号查询员工
GET /account/{id}/department/{id}
4. 分页查询部门
GET /department?currentPage=1&pageSize=10
新增示例
1. 新增部门
POST /department
2. 新增员工
POST /account
更新示例
1. 更新部门除主键的所有信息
PUT /department
2. 更新部门的名称
PUT /department
删除示例
1. 删除部门
DELETE /department/{id}
1. 删除某部门中名叫狗剩的员工
DELETE /account/{name}/department/{id}
请求参数
新增和更新
前端在调用新增和更新接口时传递的是一个对象,所以当请求参数个数等于1时,可以直接接收此参数,当参数大于1时需要新建一个DTO对象来接收。
方便接口调用方调用,我们要把对象和属性写上详细的swagger注释(
该类的作用、该值的作用、格式规则、示例)。
具体示例参考下面代码,节约篇幅省去了getter和setter:
@ApiModel("部门对象")
public class DepartmentDto {
@ApiModelProperty(value ="部门id、不得超过6位",example = "1")
private Integer id;
@ApiModelProperty(value ="部门名称、不得超过10位",example = "市场部")
private String name;
}
查询和删除
查询和删除不能新建一个对象来接受,所以只能在接口处定义swagger注释(该值的作用、格式规则、示例),并且描述该接口的作用、错误码的返回、成功的返回;
@ApiOperation(value = "根据部门id查询部门信息", notes = "根据部门id查询部门信息")
@GetMapping("/{id}")
@ApiResponses(value = {@ApiResponse(code = 200, message = "查询成功"),
@ApiResponse(code = 500, message = "systemError<br>"
+ "lengthError<br>")})
@ApiImplicitParam(name = "id",value = "部门id、不得超过6位",example = "1")
public Result<DepartmentDto> getList(@PathVariable("id") String id){
//假装查询哈
return Result.success("查询成功",new DepartmentDto());
}
响应数据
前后端分离时,我们需要定义统一的返回数据格式,并且对异常也要全局拦截。
统一返回数据对象
统一返回对象应包括以下字段,code:Http状态码、message:错误码、data:返回数据。
- 这三个字段应加上swagger注释;
- 构造方法私有化、新建静态的构建方法以便快速得到;
- 为打印日志方便可以重写toString方法;
@ApiModel("统一返回对象")
public class Result<T> {
@ApiModelProperty("HTTP 请求状态码")
private String code;
@ApiModelProperty("返回的错误码")
private String message;
@ApiModelProperty("返回数据")
private T data;
private static final String success = HttpStatus.OK.value()+"";
private static final String fail = HttpStatus.INTERNAL_SERVER_ERROR.value()+"";
private Result(String code, String message, T t) {
this.code = code;
this.message = message;
this.data = t;
}
public static Result success(String message,Object data){
return new Result(success,message,data);
}
}
全局异常拦截
异常码
新建一个异常码的枚举,方便管理存储和返回异常;代码中含有no和code的字段,code用于返回前端,no的可以由自己的业务规则生成,将这个no打印在日志中,方便日后排查问题;
public enum ExceptionEnum {
SYSTEM_ERROR("010-1000000","systemError");
private final String no;
private final String code;
ExceptionEnum(String no, String code) {
this.no = no;
this.code = code;
}
public String getNo() {
return no;
}
public String getCode() {
return code;
}
@Override
public String toString() {
return this.code;
}
}
全局异常类
新建全局异常码枚举,使用异常码管理异常;
public class BusinessException extends RuntimeException {
private static final long serialVersionUID = 1L;
private ExceptionEnum exceptionEnum;
private Object data ;
/**
* Instantiates a new Iam base exception.
*/
public BusinessException() {
}
public BusinessException(ExceptionEnum exceptionEnum) {
super(exceptionEnum.getCode());
this.exceptionEnum = exceptionEnum;
}
}
异常拦截
全局异常拦截,如果是业务异常则返回业务返回的错误码;如果是系统内部的错误比如空指针异常等等则抛出系统异常(这样处理是为了统一返回,方便前端处理,空指针异常只是示例,如果真的抛出空指针异常就要好好思考下为什么没判空!!!)
@RestControllerAdvice
public class GlobalExceptionHandler {
@ExceptionHandler(Exception.class)
public Result exception(Exception e) {
return Result.fail(ExceptionEnum.SYSTEM_ERROR.getCode());
}
@ExceptionHandler(BusinessException.class)
public Result exception(BusinessException e) {
return Result.fail(e.getCode());
}
}
接口规范示例
GET 和DELETE 接口示例
添加@ApiOperation 描述该方法
添加@ApiResponses 描述成功和失败的message 、Http请求的状态码
添加@ApiImplicitParam 描述传入参数、格式限制、默认值
@ApiOperation(value = "根据部门id查询部门信息", notes = "根据部门id查询部门信息")
@GetMapping("/{id}")
@ApiResponses(value = {@ApiResponse(code = 200, message = "查询成功"),
@ApiResponse(code = 500, message = "systemError<br>"
+ "lengthError<br>")})
@ApiImplicitParam(name = "id",value = "部门id、不得超过6位",example = "1")
public Result<DepartmentDto> getList(@PathVariable("id") String id){
//假装查询哈
return Result.success("查询成功",new DepartmentDto());
}
POST、PUT、PATCH接口示例
@ApiOperation(value = "新增部门信息", notes = "新增部门信息")
@PostMapping("/")
@ApiResponses(value = {@ApiResponse(code = 200, message = "新增成功"),
@ApiResponse(code = 500, message = "systemError<br>"
+ "lengthError<br>")})
public Result add(@RequestBody DepartmentDto dto){
//假装新增哈
return Result.success("新增成功",null);
}
API文档
按照上述的代码所写,得到的swagger文档如图:
代码
示例代码已经上传至www.fizzed.top/archives/ji…
写在最后
欢迎大家关注我的公众号【有一只基的程序猿】,一起交流Java、大数据,文章对应的脑图也会放在公众号里。 点关注,不迷路!!!
博客地址: www.fizzed.top