1 strtus2异常

Actionexecute方法声明为:
public String execute() throws Exception,这样,Action可以抛出任何Exception

1.1 自己实现异常处理

我们以helloWorldAction为例,在Actionexecute方法中这样写:

public String execute() throws Exception {  
        int a=5/0;
        this.businessExecute();  
        return "toWelcome";  
} 

上面的代码中有int a=5/0;,很显然,会抛出除数为0的错误,这个错误是RuntimeException,我们的程序没有进行相应的例外处理,则会抛给Struts2去处理。那么,在实际的项目中很显然不能这么简单而粗暴的处理错误,一种简单的处理方法就是跳转到一个错误处理页面。

假设要求这个Action,在出现ArithmeticException的时候,跳转到一个叫math-exceptionResult,而其他错误跳转到另一个叫otherwise-exceptionResult。那么,在Action中可以这么写:

public String execute() throws Exception {  
    try {  
        int a = 5/0;  
    } catch (ArithmeticException e) {  
        e.printStackTrace();  
        return "math-exception";  
    } catch (Exception e){  
        e.printStackTrace();  
        return "otherwise-exception";  
    }  
    this.businessExecute();
    return "success";  
}  

这样,在运行中出现ArithmeticException就会跳转到math-exception指定的页面,而其他Exception就会跳转到otherwise-exception指定的页面,如果没有出错,就会跳转到success指定的页面。在struts.xmlAction中,只要配置好上述三个Result就可以正常运行了。

1.2 Struts2的异常处理机制

1.2.1 局部异常映射

<action>元素中设置<exception-mapping>元素,可以指定在execute方法抛出指定错误的时候,跳转到哪个指定的页面。用Struts2的异常机制就不需要自己手动去try-catch了。action里的代码如下:

public String execute() throws Exception {  
        int a=5/0;
        this.businessExecute();  
        return "toWelcome";  
} 

然后在struts.xml<action>元素中增加<exception-mapping>子元素,示例如下:

<action name="helloworldAction" class="cn.javass.hello.struts2impl.action.HelloWorldAction">
     <exception-mapping result="math-exception" exception="java.lang.ArithmeticException"/>  
     <exception-mapping result="math-exception" exception="java.lang.Exception"/>  
     <result name="math-exception">/${folder}/error.jsp</result>    
     <result name="toWelcome">/${folder}/welcome.jsp</result> 
     <result name="input">/${folder}/login.jsp</result>   
</action>

<action>元素里面,增加了两个<exception-mapping>元素,其execption属性指定了一个Exception的全类名,如果Actionexecute方法抛出的错误是这个Exception类的实例或其派生类的实例,则会跳转到对应的result属性所指定的结果。当然,它们指定的名称为math-exceptionResult,还是需要另行配置的。

1.2.2 全局异常映射

上面的<exception-mapping>元素是作为<action>元素的子元素来配置的,只对本<action>元素有效。其实跟局部Result和全局Result一样,也可以把<exception-mapping>提到父包中,做成全局的异常映射。
全局异常映射仍然是<exception-mapping>元素,只不过不再是<action>元素的子元素,而是<global-exception-mappings>元素的子元素,而<global-exception-mappings>元素是<package>元素的子元素。当然,配置了<global-exception-mappings>,自然需要配置<global-results>
注意:<global-results>还必须在<global-exception-mappings>之前,
示例如下:

<package name="helloworld"  extends="struts-default">  
        <global-results>  
            <result name="math-exception">/${folder}/error.jsp</result>  
        </global-results>  
        <global-exception-mappings>  
            <exception-mapping result="math-exception" exception="java.lang.ArithmeticException"/>  
            <exception-mapping result="math-exception" exception="java.lang.Exception"/>  
        </global-exception-mappings>  
          
        <action name="helloworldAction" class="cn.javass.hello.struts2impl.action.HelloWorldAction"> 
            <result name="toWelcome">/${folder}/welcome.jsp</result> 
            <result name="input">/${folder}/login.jsp</result>   
        </action>  
</package>  

1.2.3 全局和局部比对

对比局部结果和全局结果的查找顺序,可以很容易的理解局部异常映射和全局异常映射的查找顺序:
首先,找自己的<action>元素的内的<exception-mapping>元素是否有匹配的,如果有就执行这个exception的映射配置,如果没有,下一步。
其次,找自己的包里面的全局异常映射,也就是到自己的<action>所在的package中,找<global-exception-mappings >元素内的< exception-mapping >元素,看看是否有匹配的,如果有就执行这个exception的映射配置,如果没有,下一步。
再次,递归的寻找自己的包的父包、祖父包中的全局异常映射是否有匹配的,如果有就执行这个exception的映射配置,如果没有,下一步。
最后,如果上述三种情况都没有的话,则将Exception抛出给Struts2去处理。

注意:如果出现同样符合条件的异常映射,上述的顺序也是异常映射之间的优先顺序,也就是说,如果Actionexecute方法抛出一个异常,而局部异常映射和全局异常映射中都有相应的配置,那会以局部异常映射为准。

1.2.4 在页面输出异常信息

在前面的示例中,当Actionexecute方法抛出一个异常之后,跳转到指定的页面,也就是error.jsp后,并没有把具体的异常信息展示出来。那么,想要在error.jsp页面上展示Exception的错误信息,该怎么做呢? 
可以使用Struts2提供的标签,来输出Exception的错误信息,如下:
<s:property value=”exception”/>仅仅简单打印出exception对象的例外消息。
<s:property value=”exceptionStack”/>可以打印出exception堆栈信息。
error.jsp的页面如下:

<%@ page language="java" contentType="text/html; charset=utf-8" pageEncoding="utf-8"%>  
 <%@ taglib prefix="s" uri="/struts-tags"%>     
<html>  
<head>  
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">  
<title>Insert title here</title>  
</head>  
<body>  
<font color=red><b>对不起,出错了,错误信息为:</b></font><br>  
<s:property value="exception"/>  
<br>  
<font color=red><b>错误的堆栈信息为:</b></font><br>  
<s:property value="exceptionStack"/>  
</body>  
</html>  

按照上面的例子,会输出以下错误:

1  对不起,出错了,错误信息为:
2 java.lang.ArithmeticException: / by zero
3 错误的堆栈信息为:
4 java.lang.ArithmeticException: / by zero at cn.javass.hello.struts2impl.action.HelloWorldAction.execute(Hello)