将Struts 2异常处理程序映射到Action

时间:2011-04-21 16:22:38

标签: exception-handling struts2

我已将Struts 2配置为将任何java.lang.Exception重定向到记录异常的特殊Action。我的重定向工作,但我的Action总是得到一个null异常(即使我明确抛出一个异常)。这是我的struts.xml文件:

<global-results>
    <result name="errHandler" type="chain">
    <param name="actionName">errorProcessor</param>
    </result>
</global-results>

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

<action name="errorProcessor" class="myErrorProcessor">
      <result name="error">/error.jsp</result>
</action>

<action name="throwExceptions" class="throwExceptions">
      <result name="success">done.jsp</result>
</action>

在我的错误处理器中,我有以下内容:

public class myErrorProcessor extends ActionSupport {

   private Exception exception;

   public String execute() {
         System.out.println("null check: " + (exception == null));
         return "error";
   }

   public void setException(Exception exception) {
         this.exception = exception;
   }

   public Exception getException() {
         return exception;
   }
}

在throwsException类中,我有以下内容:

public String execute() {
     int x = 7 / 0;
     return "success";
}

当我运行程序时,Exception处理程序总是会得到一个null异常。我正在使用链类型重定向到异常处理程序。我是否需要实现某种ExceptionAware接口? Struts 2异常setter是否除了setException之外还调用了什么?

注意:我在编写此程序时试图关注this tutorial

2 个答案:

答案 0 :(得分:7)

使用struts2版本2.3.1.2我的错误处理程序中没有得到null异常,一切都按照宣传的方式工作。确保使用未修改的defaultStack。

就可信来源而言,我们可以参考ExceptionMappingInterceptorChaining Interceptor的拦截器文档。 ExceptionMappingInterceptor将ExceptionHolder推送到值堆栈,而值堆栈又会暴露异常属性。链接拦截器将值堆栈上的所有属性复制到目标。由于ExceptionHolder在堆栈上,如果有一个Exception的setter,它将被设置。

以下是产生工作示例的所有文件:

struts.xml(与问题非常相似):

<?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">
        <global-results>
            <result name="errHandler" type="chain">
                <param name="actionName">errorProcessor</param>
            </result>
        </global-results>
        <global-exception-mappings>
            <exception-mapping exception="java.lang.Exception" result="errHandler" />
        </global-exception-mappings>
        <action name="errorProcessor" class="com.kenmcwilliams.test.myErrorProcessor">
            <result name="error">/WEB-INF/content/error.jsp</result>
        </action>
        <action name="throwExceptions" class="com.kenmcwilliams.kensocketchat.action.Bomb">
            <result name="success">/WEB-INF/content/bomb.jsp</result>
        </action>
    </package>
</struts>

MyErrorProcessor.java

package com.kenmcwilliams.test;

import com.opensymphony.xwork2.ActionSupport;

public class MyErrorProcessor extends ActionSupport {

    private Exception exception;

    @Override
    public String execute() {
        System.out.println("Is exception null: " + (exception == null));
        System.out.println(""
                + exception.getMessage());
        return "error";
    }

    public void setException(Exception exceptionHolder) {
        this.exception = exceptionHolder;
    }

    public Exception getException() {
        return exception;
    }
}

Bomb(只是抛出RuntimeException):

package com.kenmcwilliams.kensocketchat.action;

import com.opensymphony.xwork2.ActionSupport;

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

查看炸弹(/WEB-INF/content/bomb.jsp)[永远无法访问]

<%@taglib prefix="s" uri="/struts-tags"%>
<%@page contentType="text/html" pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
    <head>
        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
        <title>The Bomb!</title>
    </head>
    <body>
        <h1>The Bomb!</h1>
    </body>
</html>

查看错误(/WEB-INF/content/error.jsp)

<%@taglib prefix="s" uri="/struts-tags"%>
<%@page contentType="text/html" pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
    <head>
        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
        <title>Global Error Handler</title>
    </head>
    <body>
        <h1>Global Error Handler</h1>
        <s:property value="exception.stackTrace"/>
    </body>
</html>

输出:

我看到了error.jsp渲染,我在glassfish控制台上看到了以下内容:

INFO: Is exception null: false
INFO: Hello from Exception!

答案 1 :(得分:5)

我遇到了同样的问题!

虽然让Struts填充exception字段更加清晰,但似乎没有发生这种字段填充(如你所说)。为了解决这个问题,我从我的异常处理程序类(您的myErrorProcessor类)中删除了异常字段(及其getter / setter),并将其替换为“手动”从{{1}中提取异常的方法}:

ValueStack

然后我可以使用/** * Finds exception object on the value stack * * @return the exception object on the value stack */ private Object findException() { ActionContext ac = ActionContext.getContext(); ValueStack vs = ac.getValueStack(); Object exception = vs.findValue("exception"); return exception; } 来确保异常instanceof是我期望的类型,然后相应地处理该异常(比如将自定义Object对象中的消息写入数据库)。

让我知道这对你有用! :)