• Spring全局异常处理的三种方式


      在J2EE项目的开发中,不管是对底层的数据库操作过程,还是业务层的处理过程,还是控制层的处理过程,都不可避免会遇到各种可预知的、不可预知的异常需要处理。每个过程都单独处理异常,系统的代码耦合度高,工作量大且不好统一,维护的工作量也很大。 那么,能不能将所有类型的异常处理从各处理过程解耦出来,这样既保证了相关处理过程的功能较单一,也实现了异常信息的统一处理和维护?答案是肯定的。下面将介绍使用Spring MVC统一处理异常的解决和实现过程。

    • 使用Spring MVC提供的SimpleMappingExceptionResolver
    • 实现Spring的异常处理接口HandlerExceptionResolver 自定义自己的异常处理器
    • 使用@ExceptionHandler注解实现异常处理

      (一) SimpleMappingExceptionResolver 
      使用这种方式具有集成简单、有良好的扩展性、对已有代码没有入侵性等优点,但该方法仅能获取到异常信息,若在出现异常时,对需要获取除异常以外的数据的情况不适用。

     1 @Configuration
     2 @EnableWebMvc
     3 @ComponentScan(basePackages = {"com.balbala.mvc.web"})
     4 public class WebMVCConfig extends WebMvcConfigurerAdapter{
     5   @Bean
     6     public SimpleMappingExceptionResolver simpleMappingExceptionResolver()
     7     {
     8         SimpleMappingExceptionResolver b = new SimpleMappingExceptionResolver();
     9         Properties mappings = new Properties();
    10         mappings.put("org.springframework.web.servlet.PageNotFound", "page-404");
    11         mappings.put("org.springframework.dao.DataAccessException", "data-access");
    12         mappings.put("org.springframework.transaction.TransactionException", "transaction-Failure");
    13         b.setExceptionMappings(mappings);
    14         return b;
    15     }
    16 }

      (二) HandlerExceptionResolver
      相比第一种来说,HandlerExceptionResolver能准确显示定义的异常处理页面,达到了统一异常处理的目标
      1.定义一个类实现HandlerExceptionResolver接口

     1 public class GlobalHandlerExceptionResolver implements HandlerExceptionResolver {   
     2  private static final Logger LOG = LoggerFactory.getLogger(GlobalHandlerExceptionResolver.class);                 
     3    /**     
     4     * 在这里处理所有得异常信息     
     5     */    
     6    @Override    
     7    public ModelAndView resolveException(HttpServletRequest req,                                         HttpServletResponse resp, Object o, Exception ex) {   
     8        ex.printStackTrace();     
     9        if (ex instanceof AthenaException) {    
    10            //AthenaException为一个自定义异常
    11            ex.printStackTrace();         
    12            printWrite(ex.toString(), resp);     
    13            return new ModelAndView();  
    14         }    
    15        //RspMsg为一个自定义处理异常信息的类  
    16        //ResponseCode为一个自定义错误码的接口
    17        RspMsg unknownException = null;      
    18        if (ex instanceof NullPointerException) {        
    19            unknownException = new RspMsg(ResponseCode.CODE_UNKNOWN, "业务判空异常", null);
    20        } else {          
    21            unknownException = new RspMsg(ResponseCode.CODE_UNKNOWN, ex.getMessage(), null);        }      
    22            printWrite(unknownException.toString(), resp);   
    23            return new ModelAndView();   
    24    }  
    25 
    26    /**     
    27    * 将错误信息添加到response中     
    28    *     
    29    * @param msg     
    30    * @param response     
    31    * @throws IOException     
    32    */   
    33     public static void printWrite(String msg, HttpServletResponse response) {      
    34          try {           
    35              PrintWriter pw = response.getWriter();        
    36              pw.write(msg);       
    37              pw.flush();       
    38              pw.close();      
    39           } catch (Exception e) {          
    40              e.printStackTrace();      
    41           }   
    42     }
    43 }

      这种方式实现的异常处理,可以针对不同的异常和自己定义的异常码进行翻译,然后输出到response中,在前端展示。

      (三)@ExceptionHandler

      1.首先定义一个父类,实现一些基础的方法

     1 public class BaseGlobalExceptionHandler {    
     2      protected static final Logger logger = null;   
     3      protected static final String DEFAULT_ERROR_MESSAGE = "系统忙,请稍后再试"; 
     4 
     5      protected ModelAndView handleError(HttpServletRequest req, HttpServletResponse rsp, Exception e, String viewName, HttpStatus status) throws Exception {    
     6          if (AnnotationUtils.findAnnotation(e.getClass(), ResponseStatus.class) != null)       
     7          throw e;     
     8          String errorMsg = e instanceof MessageException ? e.getMessage() : DEFAULT_ERROR_MESSAGE;        
     9          String errorStack = Throwables.getStackTraceAsString(e);   
    10 
    11          getLogger().error("Request: {} raised {}", req.getRequestURI(), errorStack);       
    12          if (Ajax.isAjax(req)) {        
    13               return handleAjaxError(rsp, errorMsg, status);   
    14          }        
    15          return handleViewError(req.getRequestURL().toString(), errorStack, errorMsg, viewName);  
    16      }   
    17 
    18      protected ModelAndView handleViewError(String url, String errorStack, String errorMessage, String viewName) {        
    19           ModelAndView mav = new ModelAndView();       
    20           mav.addObject("exception", errorStack);        
    21           mav.addObject("url", url);     
    22           mav.addObject("message", errorMessage);  
    23           mav.addObject("timestamp", new Date());        
    24           mav.setViewName(viewName);    
    25           return mav;   
    26        }    
    27 
    28      protected ModelAndView handleAjaxError(HttpServletResponse rsp, String errorMessage, HttpStatus status) throws IOException {        
    29             rsp.setCharacterEncoding("UTF-8");       
    30             rsp.setStatus(status.value());      
    31             PrintWriter writer = rsp.getWriter();
    32             writer.write(errorMessage);        
    33             writer.flush();        
    34             return null;    
    35       }    
    36 
    37      public Logger getLogger() {       
    38            return LoggerFactory.getLogger(BaseGlobalExceptionHandler.class);
    39      } 
    40 }

      2.针对你需要捕捉的异常实现相对应的处理方式

     1 @ControllerAdvice
     2 public class GlobalExceptionHandler extends BaseGlobalExceptionHandler {    
     3 
     4       //比如404的异常就会被这个方法捕获
     5       @ExceptionHandler(NoHandlerFoundException.class)    
     6       @ResponseStatus(HttpStatus.NOT_FOUND)    
     7        public ModelAndView handle404Error(HttpServletRequest req, HttpServletResponse rsp, Exception e) throws Exception {    
     8              return handleError(req, rsp, e, "error-front", HttpStatus.NOT_FOUND);    
     9        }    
    10 
    11       //500的异常会被这个方法捕获
    12       @ExceptionHandler(Exception.class)      
    13       @ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR) 
    14       public ModelAndView handleError(HttpServletRequest req, HttpServletResponse rsp, Exception e) throws Exception { 
    15              return handleError(req, rsp, e, "error-front", HttpStatus.INTERNAL_SERVER_ERROR);  
    16       }    
    17 
    18      //TODO  你也可以再写一个方法来捕获你的自定义异常
    19      //TRY NOW!!!
    20 
    21       @Override    
    22       public Logger getLogger() {      
    23             return LoggerFactory.getLogger(GlobalExceptionHandler.class);    
    24       }
    25 
    26   }
  • 相关阅读:
    机器学习之线性回归
    斯坦福机器学习【5】生成学习算法(高斯判别与朴素贝叶斯)
    网络编程
    正则表达式
    Mysql
    python爬虫
    nginx
    maven基础
    sping入门
    河北省重大技术需求征集八稿第一天
  • 原文地址:https://www.cnblogs.com/lcngu/p/7096529.html
Copyright © 2020-2023  润新知