关于Spring MVC 异常的处理
在Spring mvc中的某个RequestHandler注解下的方法 发生异常可以直接扔出异常 交给DispatcherServlet(相当于纯Servlet实现下的MainServlet Spring 提供了实现)处理
因为 具体路径对应的具体方法是由DispatcherServlet调用的 所以如果调用方法抛出异常
dispatcherServlet 会接受异常 当dispatcherServlet捕获异常 时 会检查简单异常处理器的配置然后根据异常类型找到对应的异常处理页面
源码分析
这里使用了多个制表符 体现方法嵌套调用的关系 即每查看一个方法内部的代码 就用制表符区分上下关系
try {
ModelAndView mv = null;
Exception dispatchException = null;
try {
.....
}
catch (Exception ex) {
dispatchException = ex;
}
catch (Throwable err) {
// As of 4.3, we're processing Errors thrown from handler methods as well,
// making them available for @ExceptionHandler methods and other scenarios.
dispatchException = new NestedServletException("Handler dispatch failed", err);
}
//这句就是核心了
processDispatchResult(processedRequest, response, mappedHandler, mv, dispatchException);
//然后继续向下调用
//以下代码是processDispatchResult方法调用的processHandlerException方法
ModelAndView exMv = null;
for (HandlerExceptionResolver handlerExceptionResolver : this.handlerExceptionResolvers) {
//这是this.handlerExceptionResolvers的声明
//private List<HandlerExceptionResolver> handlerExceptionResolvers;
//问题来了 我们配置简单视图处理器明明是<props> 其实该标签对应的是map接口的java.util.Properties 为什么 这里遍历的是list呢
//答案在下面
// Find all HandlerExceptionResolvers in the ApplicationContext, including ancestor contexts.
Map<String, HandlerExceptionResolver> matchingBeans = BeanFactoryUtils
.beansOfTypeIncludingAncestors(context, HandlerExceptionResolver.class, true, false);
this.handlerExceptionResolvers = new ArrayList<HandlerExceptionResolver>(matchingBeans.values());
exMv = handlerExceptionResolver.resolveException(request, response, handler, ex);
if (exMv != null) {
break;
}
}
//
}
catch (Exception ex) {
...
}
catch (Throwable err) {
...
}
finally {
....
}
- 使用Spring MVC提供的简单异常处理器SimpleMappingExceptionResolver
<!-- 配置简单异常处理器 -->
<bean class="org.springframework.web.servlet.handler.SimpleMappingExceptionResolver">
<property name="exceptionMappings">
<props>
<!-- 如果抛出的异常时key类型 则跳转至指定的视图页面 -->
<prop key="java.lang.Exception">error</prop>
</props>
</property>
</bean>
@RequestMapping("/login.do")
public void Hello() {
Integer.parseInt("100a");
return "hello";
}
``