使用Spring MVC HandlerExceptionResolver处理异常
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>
转:http://fuliang.iteye.com/blog/947191
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· .NET周刊【3月第1期 2025-03-02】
· [AI/GPT/综述] AI Agent的设计模式综述
2011-10-25 Android应用的启动界面