拦截器抛出的异常不会转到异常处理程序。
今天我遇到了一个问题。我有一个拦截器,它开始并提交Hibernate事务,它可能在提交时抛出异常(例如org.hibernate.StaleObjectStateException
)。也就是说,它可以抛出异常,但异常不会到达处理程序。我以为我的代码有问题。但后来我写了一个简单的测试,结果是
struts.xml
中的包定义:
<package name="basicstruts2" namespace="/" extends="struts-default">
<interceptors>
<interceptor name="dummy" class="test.TestInterceptor"/>
<interceptor-stack name="myStack">
<interceptor-ref name="defaultStack" />
<interceptor-ref name="dummy" />
</interceptor-stack>
</interceptors>
<default-interceptor-ref name="myStack"/>
<global-results>
<result name="exception" type="chain">exceptionHandler</result>
</global-results>
<global-exception-mappings>
<exception-mapping exception="java.lang.Exception" result="exception" />
</global-exception-mappings>
<action name="test" class="test.TestAction">
<result>result.jsp</result>
</action>
<action name="exceptionHandler" class="test.ExceptionHandler">
<result>DebugErrorPage.jsp</result>
</action>
</package>
TestAction.java
:
package test;
public class TestAction extends ActionSupport {
private BusinessLogic logic = new BusinessLogic();
public String execute() {
logic.test();
return SUCCESS;
}
}
TestInterceptor.java
:
package test;
public class TestInterceptor implements Interceptor {
@Override
public String intercept(ActionInvocation arg0) throws Exception {
String result = null;
try {
result = arg0.invoke();
boolean flag = true;
if (flag) throw new RuntimeException("qwerty");
} catch (Exception e) {
System.out.println("exception catched in interceptor, rethrowing " + e);
throw e;
}
return result;
}
}
ExceptionHandler.java
:
package test;
public class ExceptionHandler extends ActionSupport {
private Exception exception;
public void setException(Exception e) {
exception = e;
System.out.println("setting exception");
}
public String execute() {
System.out.println("exeption in handler " + exception);
return SUCCESS;
}
}
BusinessLogic.java
:
package test;
public class BusinessLogic {
public void test() {
System.out.println("test logic");
// boolean flag = true;
// if (flag) throw new RuntimeException("qwerty");
}
}
so,控制台输出:
test logic
exception catched in interceptor, rethrowing java.lang.RuntimeException: qwerty
但如果BusinessLogic抛出异常,我们可以取消对代码的注释:
BusinessLogic.java
:
package test;
public class BusinessLogic {
public void test() {
System.out.println("test logic");
boolean flag = true;
if (flag) throw new RuntimeException("qwerty");
}
}
并注释掉拦截器中的代码:
@Override
public String intercept(ActionInvocation arg0) throws Exception {
String result = null;
try {
result = arg0.invoke();
// boolean flag = true;
// if (flag) throw new RuntimeException("qwerty");
} catch (Exception e) {
System.out.println("exception catched in interceptor, rethrowing " + e);
throw e;
}
return result;
}
输出将为:
test logic
exception catched in interceptor, rethrowing java.lang.RuntimeException: qwerty
setting exception
exeption in handler java.lang.RuntimeException: qwerty
我们将看到错误页面。
那么,有没有人能很好地解释这种行为呢?如果异常拦截器不能处理其他拦截器抛出的异常,那么将异常拦截器放在默认Struts堆栈的顶部有什么意义?为什么?? 如果您能给我一个好的答复,我将不胜感激。编辑: 有一个代码我有问题:
public String intercept(ActionInvocation arg0) throws Exception {
String result = null;
try {
sf.getCurrentSession().beginTransaction();
result = arg0.invoke();
sf.getCurrentSession().getTransaction().commit();
} catch (StaleObjectStateException staleEx) {
if (sf.getCurrentSession().getTransaction().isActive()) {
sf.getCurrentSession().getTransaction().rollback();
}
throw staleEx;
} catch (Exception ex) {
ex.printStackTrace();
try {
if (sf.getCurrentSession().getTransaction().isActive()) {
sf.getCurrentSession().getTransaction().rollback();
}
} catch (Throwable rbEx) {
}
// Let others handle it... maybe another interceptor for exceptions?
throw new ServletException(ex);
}
return result;
}
如果我希望处理commit()
引发的异常,该怎么办?
解决方案
该异常由TestInterceptor
在操作调用和结果呈现后引发。
来自Writing Interceptors page上的备注:
请记住,Invoke将在调用结果之后返回(例如。在呈现了您的JSP后),这使得它非常适合于打开视图中的会话模式之类的东西。如果要在调用结果之前执行某些操作,则应实现PreResultListener。
相关文章