全局异常处理
在 Spring 3.x 提出了 @ControllerAdvvice,可以与 @ExceptionHandler、@InitBinder、@ModelAttribute 等注解配套使用对程序异常进行处理。
异常的处理分为两类:局部异常处理和全局异常处理。
局部异常处理:@ExceptionHandler 和 @Controller 注解搭配使用,只有指定的Controller层出现了异常才会被@ExceptionHandler捕获到,但是实际开发中controller数量比较多,所以这种方式不是很适合。
全局异常处理:@ControllerAdvice搭配@ExceptionHandler用来解决全局异常。@RestControllerAdvice = @ControllerAdvice + @ResponseBody
Spring Boot 异常分类
Java中的异常有很多,按照 controller 进行分类,分为进入controller前的异常和业务层的异常。
进入controller之前的异常一般是 javax.servlet.ServletException 类型的异常,因此在全局异常处理的时候需要统一处理。几个常见异常如下:
- NoHandlerFoundException:客户端的请求没有找到对应的controller,抛出404异常;
- HttpRequestMethodNotSupportException:请求的http方法和controller允许的方法不一致;
- MissingPathVariableException:未检测到路径参数;
- MethodArgumentNotValidException:参数校验异常。
全局统一异常处理
- 建立返回状态枚举类 ResultCode
public enum ResultCode {
SUCCESS(1000, "操作成功"),
ERROR(2000, "操作失败"),
ERROR_UNKNOW(2001, "未知失败"),
;
private final Integer code;
private final String msg;
ResultCode(Integer code, String msg) {
this.code = code;
this.msg = msg;
}
public Integer getCode() {
return code;
}
public String getMsg() {
return msg;
}
}
- 建立返回数据封装类 JsonResult(部分)
@Data
public class JsonResult<T> implements Serializable {
private static final long serialVersionUID = 1L;
private Integer code;
private String msg;
private T data;
public static JsonResult success() {
JsonResult<Object> result = new JsonResult<>();
result.setCode(ResultCode.SUCCESS.getCode());
result.setMsg(ResultCode.SUCCESS.getMsg());
return result;
}
public static <T> JsonResult<T> success(T data) {
JsonResult<T> result = new JsonResult<>();
result.setCode(ResultCode.SUCCESS.getCode());
result.setMsg(ResultCode.SUCCESS.getMsg());
result.setData(data);
return result;
}
public static JsonResult error() {
JsonResult<Object> result = new JsonResult<>();
result.setCode(ResultCode.ERROR.getCode());
result.setMsg(ResultCode.ERROR.getMsg());
return result;
}
public static JsonResult error(ResultCode resultCode) {
JsonResult<Object> result = new JsonResult<>();
result.code = resultCode.getCode();
result.msg = resultCode.getMsg();
return result;
}
}
- 新建自定义异常 TipException,继承RuntimeException类
@Data
public class TipException extends RuntimeException {
private ResultCode resultCode;
public TipException(ResultCode resultCode) {
this.resultCode = resultCode;
}
}
- 全局异常处理类 GlobalExceptionHandler
@ControllerAdvice
public class GlobalExceptionHandle {
// 指定捕获的异常
@ExceptionHandler(Exception.class)
@ResponseBody
public JsonResult tipExceptionHandle(HttpServletRequest request, Exception e, HttpServletResponse response) {
TipException tipException = (TipException) e;
JsonResult<Object> result = new JsonResult<>();
return result.error(tipException.getResultCode());
}
}
- 测试controller
@RestController
@RequestMapping("error")
public class ErrorController {
@GetMapping("success")
public JsonResult success() {
return JsonResult.success();
}
@GetMapping("error")
public JsonResult error(){
return JsonResult.error();
}
@GetMapping("errorthrow")
public JsonResult errorThrow() {
if (true) {
// 抛出自定义异常,正常业务一般在service层抛出,这里仅作为测试demo
throw new TipException(ResultCode.ERROR_UNKNOW);
}
return JsonResult.error();
}
}
请求对应的地址后,返回的数据为封装的JsonResult对应的json格式数据。
{
"code": 1000,
"msg": "操作成功",
"data": null
}