【问题标题】:Struts 2 - How to redirect exceptions of type Exception to a particular page, but not handle a particular exception?Struts 2 - 如何将 Exception 类型的异常重定向到特定页面,但不处理特定异常?
【发布时间】:2012-04-25 09:54:50
【问题描述】:

我希望将所有Exception 类型的错误重定向到结果“error”。为此,我这样做了:

<global-exception-mappings>
          <exception-mapping result="error" exception="java.lang.Exception"></exception-mapping>
</global-exception-mappings>

但我不想处理特定的异常,特别是应该允许进一步传播的 org.springframework.security.access.AccessDeniedException。我怎样才能做到这一点?

【问题讨论】:

标签: exception-handling struts2 struts


【解决方案1】:

使用instanceof 运算符并从异常处理程序中重新抛出所需的异常。

我用拦截器管理它(这是我曾经尝试过的):

package com.kenmcwilliams.interceptor;

import com.opensymphony.xwork2.ActionContext;
import com.opensymphony.xwork2.ActionInvocation;
import com.opensymphony.xwork2.interceptor.Interceptor;
import java.util.logging.Level;
import java.util.logging.Logger;

public class Rethrower implements Interceptor{
    @Override
    public void destroy() {
    }

    @Override
    public void init() {
    }

    @Override
    public String intercept(ActionInvocation invocation){
        System.out.println("Start rethrower!");
        String result = "success";
        try {
            result = invocation.invoke();
        } catch (Exception ex) {
            Logger.getLogger(Rethrower.class.getName()).log(Level.SEVERE, null, ex);
        }
        Object exception = ActionContext.getContext().getValueStack().findValue("exception");
        if (exception instanceof RuntimeException){
            System.out.println("DOING RETHROW!");
            RuntimeException e = (RuntimeException)exception;
            throw e;
        }
        System.out.println("After rethrower!");
        return result;
    }
}

这里是struts.xml(为了节省查找struts dtd的时间):

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE struts PUBLIC
"-//Apache Software Foundation//DTD Struts Configuration 2.3//EN"
"http://struts.apache.org/dtds/struts-2.3.dtd">

<struts>
    <constant name="struts.devMode" value="true" />
    <constant name="struts.ui.theme" value="simple" />
    <package  name="kenmcwilliams"  namespace="/" extends="struts-default">
        <interceptors>
            <interceptor name="rethrower" class="com.kenmcwilliams.interceptor.Rethrower"/>
            <interceptor-stack name="rethrow-stack">
                <interceptor-ref name="rethrower"/>
                <interceptor-ref name="defaultStack"/>
            </interceptor-stack>
        </interceptors>
        <global-results>
            <result name="error" >/WEB-INF/content/error.jsp</result>
        </global-results>
        <global-exception-mappings>
            <exception-mapping exception="java.lang.Exception" result="error"/>
        </global-exception-mappings>
        <action name="mybomb" class="com.kenmcwilliams.kensocketchat.action.Bomb">
            <interceptor-ref name="rethrow-stack"/>
            <result>/WEB-INF/content/bomb.jsp</result>
        </action>
    </package>
</struts>

最后是动作(它只是抛出一个运行时异常):

package com.kenmcwilliams.kensocketchat.action;

import com.opensymphony.xwork2.ActionSupport;

public class Bomb extends ActionSupport{
    @Override
    public String execute() throws Exception{
        throw new RuntimeException();
    }
}

【讨论】:

  • 我照你说的做了,stackoverflow.com/questions/5736618/…,它说“检测到无限递归”,这是意料之中的,因为我们不断抛出我们正在捕获的相同异常,并且它不断被一次又一次地捕获。我不希望 Struts 处理这个特殊的异常。
  • 抱歉,重新考虑。
  • 您已经在拦截器堆栈的顶部添加了 Rethrower 拦截器,因此默认的 ExceptionMappingInterceptor 将有机会在此之前执行,它甚至会将 RuntimeException 映射到“error.jsp”。 Rethrower 甚至可能没有机会看到这个异常。我说的对吗?
  • 两者都不会执行(这可能不是您想要的,但通常这会让您向用户显示错误,然后我假设异常不是更改视图而是进行一些清理) .我认为 ExceptionMappingInterceptor 以某种方式将异常放入 valuestack 中(没有检查过这个)。因为 rethrower 会检查 valuestack 中是否有一个带有“异常”键的对象,所以颠倒顺序是行不通的。如果您不想两者都做,那么我认为您需要实现自己的 ExceptionMappingInterceptor 并替换它。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-06-02
相关资源
最近更新 更多