本文使用 @ControllerAdvice + @ExceptionHandler 进行全局的 Controller 层异常处理。只要设计得当,就再也不用在 Controller 层进行 try-catch 了!
一、经典案例
需求:希望通过全局统一的异常处理将自定义错误码以json的形式发送给前端。
1 统一返回结果类 ApiResult
首先,定义一个统一结果返回类,最终需要将这个结果类的内容返回给前端。
package com.suncl.test2spring.exception;
import lombok.Data; @Data public class ApiResult { private String code; private String msg; public ApiResult(String code, String msg) { this.code = code; this.msg = msg; } public ApiResult(ResultCode resultCode) { this.code = resultCode.getCode(); msg = resultCode.getMsg(); } }
2 错误码枚举类 ResultCode
package com.suncl.test2spring.exception;
public enum ResultCode { /** * 成功 */ SUCCESS("200", "success"), /** * 未知错误 */ BIZ_ERROR("505", "biz error"), /** * 未知错误 */ UNKNOWN_ERROR("504", "unkonwn error"); /** * 结果码 */ private String code; /** * 结果码描述 */ private String msg; ResultCode(String code, String msg) { this.code = code; this.msg = msg; } public String getCode() { return code; } public String getMsg() { return msg; } }
3 自定义业务异常类 BizException
package com.suncl.test2spring.exception;
import lombok.extern.slf4j.Slf4j; @Slf4j public class BizException extends RuntimeException { public BizException() { } public BizException(String message) { super(message); log.error(message); } public BizException(String message, Throwable cause) { super(message, cause); log.error(message); } public BizException(Throwable cause) { super(cause); } }
4 定义全局异常处理类
- 通过 @ControllerAdvice 指定该类为 Controller 增强类。
- 通过 @ExceptionHandler 自定捕获的异常类型。
- 通过 @ResponseBody 返回 json 到前端。
package com.suncl.test2spring.exception;
import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Component; import org.springframework.web.bind.annotation.ControllerAdvice; import org.springframework.web.bind.annotation.ExceptionHandler; import org.springframework.web.bind.annotation.ResponseBody; /** * 全局Controller层异常处理类-ControllerAdvice+ExceptionHandler 方式 */ @ControllerAdvice @Slf4j public class GlobalExceptionResolver { /** * 处理所有不可知异常 * * @param e 异常 * @return json结果 */ @ExceptionHandler(Exception.class) @ResponseBody public ApiResult handleException(Exception e) { // 打印异常堆栈信息 log.error(e.getMessage(), e); return new ApiResult(ResultCode.UNKNOWN_ERROR); } /** * 处理所有业务异常 * * @param e 业务异常 * @return json结果 */ @ExceptionHandler(BizException.class) @ResponseBody public ApiResult handleOpdRuntimeException(BizException e) { // 不打印异常堆栈信息 log.error(e.getMessage(),e); return new ApiResult(ResultCode.BIZ_ERROR.getCode(),e.getMessage()); } }
5 测试
上述写法对于系统中抛出的
throw new RuntimeException("未知异常出现了");
返回结果为 {"code":"504","msg":"unkonwn error"}
throw new BizException("用户id不可为空");
返回结果为 {"msg":"用户id不可为空","code":"505"}