type
Post
status
Published
date
Nov 2, 2021
slug
summary
介绍SpringBoot项目中通用的统一异常处理方式
tags
项目方案
category
技术分享
icon
password
SpringMVC 异常机制
原则:MVC 三层出现的异常都通过 throws 抛出,最终由前端控制器 DispatcherServlet 捕获,交由异常处理器 HandlerExceptionResolver 处理
- HandlerExceptionResolver 是异常处理器接口,实现这个接口可以自定义异常处理器
- HTTP 异常可以在 web.xml 中配置自定义异常页面
<!--处理500异常--> <error-page> <error-code>500</error-code> <location>/500.html</location> </error-page> <!--处理404异常--> <error-page> <error-code>404</error-code> <location>/404.html</location> </error-page>
最佳实践
异常枚举
异常枚举
ExceptionEnum 用于和和前端约定好异常状态码和消息,并传入自定义的异常类进行统一处理public enum ExceptionEnum { /* * 用户模块异常 * */ NEED_USR_NAME(10001,"用户名不能为空"), /* * 系统异常*/ SYSTEM_ERROR(20000,"服务器内部异常"); //.....其他 Integer code; String msg; ExceptionEnum(Integer code, String msg) { this.code = code; this.msg = msg; } public Integer getCode() { return code; } public void setCode(Integer code) { this.code = code; } public String getMsg() { return msg; } public void setMsg(String msg) { this.msg = msg; } }
封装业务异常类
封装 BusinessException 继承 RuntimeException ,用来规定异常的消息结构,封装异常操作的相关方法
public class BusinessException extends RuntimeException { /** * 异常状态码 */ private Integer code = 500; /** * 异常描述信息 */ private String msg; public BusinessException(Integer code, String msg) { this.code = code; this.msg = msg; } public BusinessException(String msg) { super(msg); this.msg = msg; } public BusinessException(String msg, Throwable e) { super(msg, e); this.msg = msg; } public BusinessException(Integer code, String msg, Throwable e) { super(msg, e); this.code = code; this.msg = msg; }
全局异常处理器
- 创建 GlobalExceptionHandler 实现 HandlerExceptionResolver接口
重写resolveException方法,并配置为Bean,使用 @ControllerAdvice 注解设置为全局异常处理类
- @ExceptionHandler 可以指定方法所拦截的异常类型,实现异常的分类处理
@ControllerAdvice public class GlobalExceptionHandler { private final Logger log= LoggerFactory.getLogger(GlobalExceptionHandler.class); @ExceptionHandler(Exception.class) @ResponseBody public Object handleException(Exception e){ log.error("SYSTEM Exception:"+e); return ApiCommonResponse.error(ExceptionEnum.SYSTEM_ERROR); } @ExceptionHandler(CommonException.class) @ResponseBody public Object handleException(CommonException e){ log.error("CommonException:"+e); return ApiCommonResponse.error(e.getCode(),e.getMessage()); } }
这里使用了 统一返回对象,在另一篇文章中有介绍,如果不使用统一返回对象进行返回,也可以直接返回异常消息
public class GlobalExceptionHandler { @ResponseBody @ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR) @ExceptionHandler(Exception.class) public String exceptionHandler(Exception e) { log.error("业务异常", e); if (e instanceof MethodArgumentNotValidException) { MethodArgumentNotValidException exception = (MethodArgumentNotValidException) e; return exception.getBindingResult().getFieldError().getDefaultMessage(); } else if (e instanceof BusinessException) { BusinessException exception = (BusinessException) e; return exception.getMsg(); } else if (e instanceof UnauthorizedException) { return "权限不足"; } else { BarkMonitorUtil.sendWithGroup("没有预料的异常:" + e.getMessage(), "YOAS办公系统"); return "系统内部错误"; } } }
Relate Posts