首先 新建一個類 AppHandlerExceptionResolver 繼承 DefaultErrorAttributes, 類DefaultErrorAttributes是實現接口HandlerExceptionResolver的。
然后 需要在 tomcat等容器啟動時 加載類 AppHandlerExceptionResolver的bean, 采用類注解的模式(@Configuration和@Bean):
新建類: WebMvcConfig :
@Configuration public class WebMvcConfig extends WebMvcConfigurerAdapter { @Bean public DefaultErrorAttributes get() { AppHandlerExceptionResolver resolver = new AppHandlerExceptionResolver(); return resolver; }
在 容器啟動時,會加載 類 WebMvcConfig 到Spring容器;
重寫 AppHandlerExceptionResolver 方法中的
resolveException(HttpServletRequest request, HttpServletResponse response,Object handler, Exception e)
容器啟動完成之后,調用Controller方法,此時會調用到 接口HandlerExceptionResolver的方法resolveException(HttpServletRequest request, HttpServletResponse response,Object handler, Exception e)的方法實現,
自然會調用到 子類 AppHandlerExceptionResolver中的 resolveException(HttpServletRequest request, HttpServletResponse response,Object handler, Exception e)方法:
此時處理的異常是非業務異常: 包括參數類型不匹配,參數綁定失敗,參數格式校驗失敗, 容器運行時異常(包括outOfMemory,數組越界等);
對方法resolveException 捕獲到的 Exception e 異常進行 類型判斷; 針對不同的類型,返回對應的信息:
代碼如下:
@Override public ModelAndView resolveException(HttpServletRequest request, HttpServletResponse response, Object handler, Exception e) { ModelAndView mv = new ModelAndView(); View view = createView(e); mv.setView(view); return mv; } private View createView(Exception e) { MappingJackson2JsonView view = new MappingJackson2JsonView(); String message = ""; String code = ""; //如果是系統自定義異常 if (e instanceof BusinessException) { BusinessException ae = (BusinessException) e; message = ae.getMessage(); code = ae.getCode(); } else if (e instanceof ConstraintViolationException) { ConstraintViolationException cve = (ConstraintViolationException) e; ConstraintViolation<?> error = cve.getConstraintViolations().iterator().next(); code = "500"; message = error.getMessage(); e = new RuntimeException(message); } else if(e instanceof BindException) { // message = "上送參數"+((BindException) e).getBindingResult().getObjectName()+"字段類型匹配失敗"; message = "上送參數"+((BindException) e).getBindingResult().getObjectName()+"字段類型匹配失敗"; code = "100102005"; }else{ //如果是未知異常 // TODO 硬編碼 code = "500"; message = "服務器繁忙, 請稍后再試"; } e.printStackTrace(); view.addStaticAttribute("success", false); view.addStaticAttribute("message", message); view.addStaticAttribute("code", code); // 如果不是生產環境 // if (!appEnvironment.getEnvironment().isProdEnv()) { // view.addStaticAttribute("trace", ExceptionUtils.getStackTrace(e)); // } return view; }