• 使用Spring MVC HandlerExceptionResolver处理异常


    转载出处:http://fuliang.iteye.com/blog/947191  

    Spring MVC的确很强大,在每一个你想的到和想不到的地方都会留下钩子,来插入自定义的实现,透明替换默认实现, 

    拦截器堆栈结构设计的非常强大,多种试图的解析,url mapping的多种实现,Locale resolver、Theme resolver 
    、multipart file resolver,Excepiton hanlder Resolver等等,能让Spring MVC从1.0到3.0经历巨大变化, 
    仍能向后兼容,并支持很酷的RESTful风格和强大的简化xml配置的注解。 
    这些功能我们在项目中经常用到,但是Excepiton hanlder Resolver可能是个生僻一点的东东,因为我们通常对错误 
    的处理通常不是非常的复杂,很多情况下只是根据异常或者http error code跳转到错误页面,这个是JSP/servlet就可
    以搞定,在web.xml配置一下即可。 

    今天遇到一个事情,让我想用到HandlerExceptionResolver这个东东来处理异常。今天准备把自助系统进入上线状态, 
    所以把log的级别从DEBUG调到INFO,结果没有catch的Runtime异常在log记录,后来跟踪了一下原来Spring把异常处理的log, 
    直接使用的是debug,而不是error,所以log级别设置为INFO导致异常没有记录,看了一下spring的源代码: 
    Java代码  收藏代码
    1. // Check registerer HandlerExceptionResolvers...  
    2. ModelAndView exMv = null;  
    3. for (Iterator it = this.handlerExceptionResolvers.iterator(); exMv == null && it.hasNext();) {  
    4. HandlerExceptionResolver resolver = (HandlerExceptionResolver) it.next();  
    5. exMv = resolver.resolveException(request, response, handler, ex);  
    6. }  
    7. if (exMv != null) {  
    8. if (logger.isDebugEnabled()) {  
    9. logger.debug("Handler execution resulted in exception - forwarding to resolved error view: " + exMv, ex);  
    10. }  
    11. WebUtils.exposeErrorRequestAttributes(request, ex, getServletName());  
    12. return exMv;  
    13. }  

    可以看到可以插入自己的HandlerExceptionResover来搞定这个问题,我们可以在resolveException方法任意处理异常和log。也可以 
    把错误信息个性化后传到view层显示。 
    我们只有简单的需求,就是把没有catch的异常记入log,将异常的完整信息放在错误页面的一个隐藏的区域,方便查找出现错误的原因。 
    首先我们实现HandlerExceptionResolver 
    Java代码  收藏代码
    1. package com.qunar.advertisement.exception;  
    2.   
    3. import java.util.HashMap;  
    4. import java.util.Map;  
    5.   
    6. import javax.servlet.http.HttpServletRequest;  
    7. import javax.servlet.http.HttpServletResponse;  
    8.   
    9. import org.apache.log4j.Logger;  
    10. import org.springframework.web.servlet.HandlerExceptionResolver;  
    11. import org.springframework.web.servlet.ModelAndView;  
    12.   
    13. import com.qunar.advertisement.utils.StringPrintWriter;  
    14.   
    15. public class QADHandlerExceptionResolver implements HandlerExceptionResolver{  
    16.     private static Logger logger = Logger.getLogger(QADHandlerExceptionResolver.class);  
    17.     @Override  
    18.     public ModelAndView resolveException(HttpServletRequest request,  
    19.             HttpServletResponse response, Object handler, Exception ex) {  
    20.         logger.error("Catch Exception: ",ex);//把漏网的异常信息记入日志  
    21.         Map<String,Object> map = new HashMap<String,Object>();  
    22.         StringPrintWriter strintPrintWriter = new StringPrintWriter();  
    23.         ex.printStackTrace(strintPrintWriter);  
    24.         map.put("errorMsg", strintPrintWriter.getString());//将错误信息传递给view  
    25.         return new ModelAndView("error",map);  
    26.     }  
    27.   
    28. }  

    我们还需要一个辅助的类StringPrintWriter,因为ex.printStackTrace参数只有个PrintWriter类型的,java自带的StringWriter 
    不可用,所以我们需要自己实现一个装饰器的StringPrintWriter。 
    Java代码  收藏代码
    1. package com.qunar.advertisement.utils;  
    2.   
    3. import java.io.PrintWriter;  
    4. import java.io.StringWriter;  
    5.   
    6. public class StringPrintWriter extends PrintWriter{  
    7.   
    8.     public StringPrintWriter(){  
    9.         super(new StringWriter());  
    10.     }  
    11.      
    12.     public StringPrintWriter(int initialSize) {  
    13.           super(new StringWriter(initialSize));  
    14.     }  
    15.      
    16.     public String getString() {  
    17.           flush();  
    18.           return ((StringWriter) this.out).toString();  
    19.     }  
    20.      
    21.     @Override  
    22.     public String toString() {  
    23.         return getString();  
    24.     }  
    25. }  

    我们只需要在xml中配置一下就可以了: 
    Xml代码  收藏代码
    1. <bean class="com.qunar.advertisement.exception.QADHandlerExceptionResolver">  
    2. </bean>  

    我们在错误页面隐藏区域显示错误信息: 
    Html代码  收藏代码
    1. <div style="display:none;">  
    2.      <c:out value="${errorMsg}"></c:out>  
    3. </div>  
  • 相关阅读:
    java.lang.IllegalAccessError: tried to access field org.slf4j.impl.StaticLoggerBinder.SINGLETON from class org.slf4j.LoggerFactory
    项目开发中关于权限的实现方案简单描述(帮助以后回忆)
    一些比较有用的模板
    递归之遍历部门
    关于s2sh框架关于hibernate懒加载问题的说明和解决方案
    Hibernate实体映射配置(XML)简单三步完美配置
    项目添加性能监控日志
    redis常用命令大全
    redis主从同步
    redis之哨兵部署运行日志解读
  • 原文地址:https://www.cnblogs.com/chenying99/p/2437200.html
Copyright © 2020-2023  润新知