##关于SSH中异常处理的冲突引起的无限循环-Infinite recursion detected: [……]-问题处理
项目相关架构版本信息 - Spring4+Hibernate4+Struts2.5
先将异常处理说明如下 -
1、Spring的异常处理
采用切面类的AOP编程完成相关处理
<bean id="exceptionAspect" class="fjw.spring.aop.xml.aspect.exception.ExceptionAspect">
<property name="order" value="20"/>
</bean>
<aop:aspect ref="exceptionAspect">
<aop:after-throwing method="exceptionAdvice" pointcut-ref="commonPC" throwing="aimMethodException"/>
</aop:aspect>
会完成异常信息的相关处理
2、Struts2的异常处理
<!-- 声明默认的全局结果集 -->
<global-results>
<result name="errorHandler" type="chain">
<param name="actionName">errorProcessor</param>
</result>
</global-results>
<global-exception-mappings>
<!-- 添加配置一个Struts2的全局异常的结果处理器 -->
<exception-mapping exception="java.lang.Throwable"
result="errorHandler" />
</global-exception-mappings>
<action name="errorProcessor" class="fjw.struts2.web.action.ErrorProcessor">
<!-- 采用上述的默认的全局结果集是不行的 - 这里针对的是成功的返回 -->
<result>/error.jsp</result>
</action>
内部的处理简略如下
@Override
public String execute() throws Exception {
ActionContext.getContext().getValueStack().push(exception.getMessage());
return super.execute();
}
3、之所以会出现类似Infinite recursion detected的原因分析
Infinite recursion detected: [//saveClasses!saveClasses, //errorProcessor, //errorProcessor] 的错误,
错误提示非常不明显 - 容易产生误解。
可以理解为Struts2内部会出现这种形式的错误抛出。 这是框架内部的处理。
但是,既然是报错,而且没有正常报出, 考虑到可能是错误处理的冲突问题。
但是测试之后,发现 - 这种简单的配置和处理方式的情况下,内部的异常被捕获之后, 未能正常执行和返回结果集,
而且 Spring对应的exceptionAdvice方法未进入 Struts2对应的ErrorProcessor的方法也未进入执行。
后续测试又发现, 只有Spring的异常处理的时候,相关切面类的方法并未执行。 也就是说,Spring未捕获到错误的抛出。
而程序中断于Struts2内部的堆栈信息提示 -
java.lang.NoSuchMethodException: fjw.struts2.web.interceptor.CostTimeInterceptor.intercept()
证明在Struts2与Spring进行整合的时候, 谁先捕获到错误,会直接完成处理, 程序中断,另一个是不会继续执行了。
但是上述分析到的java.lang.NoSuchMethodException,
4、为什么Struts2的自定义方案中未能进行捕获呢?
后续测试,发现,通过上述的配置 Struts2的exception拦截器捕获到了异常 java.lang.NoSuchMethodException
然而,程序没有中断,后续陆续的捕获到了 java.lang.ReflectiveOperationException
然后,后续又继续捕获到了 java.lang.NoSuchMethodException java.lang.ReflectiveOperationException ……
所以说,最后抛出了这样的异常信息 - Stacktraces Infinite recursion detected: [//saveClasses!saveClasses, //errorProcessor, //errorProcessor] - [unknown location]
抛出的这个,还是Struts2自身的模板方案,根本没引起自定义异常处理内容的执行。说明Struts2内部,把这种抛出本身作为了一个异常进行了显示。
抛出第一个错误的时候,Struts2内部的程序未中断和返回,而是试图继续捕获后续的错误。 这种情况下,如果是Struts2内部自己处理的话,可以正常抛出相关的内容
Stacktraces
java.lang.NoSuchMethodException: fjw.struts2.web.interceptor.CostTimeInterceptor.intercept()
查看其内部执行代码的流程的话 虽然异常的捕获流程完全相同, 但是,其使用的是模板技术下的界面
Template template = config.getTemplate("/org/apache/struts2/dispatcher/error.ftl");
可以正常显示出错误信息
而上述的简单的异常处理,需要返回到某个视图,但是因为涉及到多个错误。 不使用模板技术,而响应视图的时候,Struts2无法做出正确响应。
而在正常的业务流程中,这一类错误是不需要特殊处理的,需要在项目开发过程中,即予以消除。
只需要处理自己自定义的特殊错误即可。
多个异常的自定义处理,采用下述代码样式即可。
Below is an example of global and local exception mappings.
snippet from struts.xml
<struts>
<package name="default">
...
<global-results>
<result name="login" type="redirect">/Login.action</result>
<result name="Exception">/Exception.jsp</result>
</global-results>
<global-exception-mappings>
<exception-mapping exception="java.sql.SQLException" result="SQLException"/>
<exception-mapping exception="java.lang.Exception" result="Exception"/>
</global-exception-mappings>
...
<action name="DataAccess" class="com.company.DataAccess">
<exception-mapping exception="com.company.SecurityException" result="login"/>
<result name="SQLException" type="chain">SQLExceptionAction</result>
<result>/DataAccess.jsp</result>
</action>
...
</package>
</xwork>
那么,也就不会出现上述问题。
至于,此例为何抛出NoSuchMethodException,请见前文 - 关于 Spring AOP 中,包含参数的成员方法的调用,出现 NoSuchMethodException 的研究 这个,与AOP中的动态代理使用的切入点表达式的自动生成有关系。
5、由此获得结论
在全局异常处理中,异常最好有更强的针对性。 程序运行中的异常,是可提前消除的,不要再去使用全局方案。
如需要转载 请注明文章出处 **https://my.oschina.net/u/3032872/blog/1648372 ** 谢谢~