spring 捕获未catch异常

转载请标明出处: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的源代码:
// Check registerer HandlerExceptionResolvers...
ModelAndView exMv = null;
for (Iterator it = this.handlerExceptionResolvers.iterator(); exMv == null && it.hasNext();) {
HandlerExceptionResolver resolver = (HandlerExceptionResolver) it.next();
exMv = resolver.resolveException(request, response, handler, ex);
}
if (exMv != null) {
if (logger.isDebugEnabled()) {
logger.debug("Handler execution resulted in exception - forwarding to resolved error view: " + exMv, ex);
}
WebUtils.exposeErrorRequestAttributes(request, ex, getServletName());
return exMv;
}

可以看到可以插入自己的HandlerExceptionResover来搞定这个问题,我们可以在resolveException方法任意处理异常和log。也可以
把错误信息个性化后传到view层显示。
我们只有简单的需求,就是把没有catch的异常记入log,将异常的完整信息放在错误页面的一个隐藏的区域,方便查找出现错误的原因。
首先我们实现HandlerExceptionResolver
package com.qunar.advertisement.exception;

import java.util.HashMap;
import java.util.Map;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.log4j.Logger;
import org.springframework.web.servlet.HandlerExceptionResolver;
import org.springframework.web.servlet.ModelAndView;

import com.qunar.advertisement.utils.StringPrintWriter;

public class QADHandlerExceptionResolver implements HandlerExceptionResolver{
    private static Logger logger = Logger.getLogger(QADHandlerExceptionResolver.class);
    @Override
    public ModelAndView resolveException(HttpServletRequest request,
            HttpServletResponse response, Object handler, Exception ex) {
        logger.error("Catch Exception: ",ex);//把漏网的异常信息记入日志
        Map<String,Object> map = new HashMap<String,Object>();
        StringPrintWriter strintPrintWriter = new StringPrintWriter();
        ex.printStackTrace(strintPrintWriter);
        map.put("errorMsg", strintPrintWriter.getString());//将错误信息传递给view
        return new ModelAndView("error",map);
    }

}

我们还需要一个辅助的类StringPrintWriter,因为ex.printStackTrace参数只有个PrintWriter类型的,java自带的StringWriter
不可用,所以我们需要自己实现一个装饰器的StringPrintWriter。
package com.qunar.advertisement.utils;

import java.io.PrintWriter;
import java.io.StringWriter;

public class StringPrintWriter extends PrintWriter{

    public StringPrintWriter(){
        super(new StringWriter());
    }

    public StringPrintWriter(int initialSize) {
          super(new StringWriter(initialSize));
    }

    public String getString() {
          flush();
          return ((StringWriter) this.out).toString();
    }

    @Override
    public String toString() {
        return getString();
    }
}

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

我们在错误页面隐藏区域显示错误信息:
<div style="display:none;">
     <c:out value="${errorMsg}"></c:out>
</div>
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值