1. RESTful 异常处理设计
具体设计思路可以参考 响应篇1–理论
正常返回可以参考 响应篇2–正常返回
// 异常响应
// 响应头
HTTP/1.1 400 Bad Request
Content-Type: application/json
// 响应体
{
"code": 1000,// 业务状态码
"msg": "验证失败",// 业务详细信息
"errors": [// 多个错误信息(如验证)
{"code": 2000, "msg": "错误信息"},
{"code": 2001, "msg": "错误信息"}
]
}
2. 核心类
2.1. RestfulResult (统一返回格式)
/**
* @Author geek_lazy
*/
// 篇幅原因,使用 @Data 省略 getter 和 setter 方法
@Data
public class RestfulResult<T> {
private T data;// 响应数据
private int code;// 业务状态码
private String msg;// 业务详细信息
private Page paging;// 分页信息
private String links;// 相关链接
private Object errors;// 多个错误信息(如验证)
public RestfulResult() {
// 无参构造的时候给一个成功的默认值
this.code = ResultCode.SUCCESS.code();
this.msg = ResultCode.SUCCESS.msg();
this.data = data;
}
// 这里我只写一个构造方法,根据情况可以自己定义
public RestfulResult(ResultCode code, T data) {
this.code = code.code();
this.msg = code.msg();
this.data = data;
}
}
2.2. ResultCode (业务状态码)
/**
* @Author geek_lazy
*/
@Data
public enum ResultCode {
UNKNOWN_ERROR(0, "未知错误"),// 默认错误
SUCCESS(1, "成功"),
PARAM_IS_INVALID(10001, "参数无效"),
USER_NOT_LOGGED_IN(20001, "用户未登录"),
// ...
;
private int code;// 业务状态码
private String msg;// 业务详细信息
private HttpStatus httpStatus;// 业务对应 HTTP 状态码
ResultCode(int code, String msg, HttpStatus httpStatus) {
this.code = code;
this.msg = msg;
this.httpStatus = httpStatus;
}
}
2.3. BizException (业务异常)
/**
* @Author geek_lazy
*/
public class BizException extends RuntimeException{
private int bizCode;// 业务状态码
private HttpStatus httpStatus;// HTTP 状态码
public BizException(ResultCode resultCode){
super(resultCode.msg());
this.bizCode = resultCode.code();
this.httpStatus = resultCode.httpStatus();
}
public BizException(int code, String message) {
super(message);
this.bizCode = code;
this.httpStatus = HttpStatus.BAD_REQUEST;
}
}
2.4. GlobalExceptionHandler (全局异常处理)
这里使用的是 Spring 的 @ControllerAdvice 和 @ExceptionHandler 来进行全局异常处理
/**
* @Author geek_lazy
*/
@RestController
@ControllerAdvice
public class GlobalExceptionHandler {
private static final String DEFAULT_MESSAGE = "No message available";// 没有错误信息时默认返回
/**
* 处理业务异常
* @param e
* @return
*/
@ExceptionHandler(value = BizException.class)
public Object bizExceptionHandler(BizException e) {
RestfulResult restfulResult = new RestfulResult();
restfulResult.setCode(e.getBizCode());
restfulResult.setMsg(e.getMessage());
return ResponseEntity.status(e.getHttpStatus()).body(restfulResult);
}
/**
* 默认异常处理
* @param e
* @return
*/
@ExceptionHandler(value = Exception.class)
public Object defaultExceptionHandler(Exception e) {
RestfulResult restfulResult = new RestfulResult();
restfulResult.setMsg(e.getMessage());
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(restfulResult);
}
}
3. 实践
完成上面的几个关键类后, 异常处理就基本完成了, 一般controller抛出异常大致如下:
controller
/**
* @Author geek_lazy
*/
@RestController
@RequestMapping("/statistics")
public class StatisticController {
// service层我就不写了,理解为上
@Autowired
private IStatisticService iss;
/**
* 获取一个Statistic对象
*/
@GetMapping("{statisticId}")
public Statistic getStatisticById(@PathVariable("statisticId") String statisticId) {
if (statisticId == null) {
throw new BizException(ResultCode.PARAM_IS_INVALID);
}
return iss.getStatisticById(statisticId);
}
}