Struts2的异常映射

5.5 Struts2的异常映射

5.5.1 异常映射基础

在Action中execute方法的方法签名为public String execute() throws Exception,这样,Action可以抛出任何Exception,那么,Exception抛给谁呢?

1:自己实现异常处理

来做一个简单的试验,在Action的方法中这样写:

java代码:
  1. public String execute() throws Exception {
  2. int a = 5/0;
  3. return this.SUCCESS;
  4. }
public String execute() throws Exception {
		int a = 5/0;
		return this.SUCCESS;
}

上面的代码中有int a=5/0;,很显然,会抛出除数为0的错误,这个错误是RuntimeException,我们的程序没有进行相应的例外处理,则会抛给Struts2去处理。运行结果如下图所示:

图5.3 报例外的页面

可见,这个错误直接被抛给了web容器,Struts2并没有处理。那么,在实际的项目中很显然不能这么简单而粗暴的处理错误,一种简单的处理方法就是跳转到一个错误处理页面。

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

java代码:
  1. public String execute() throws Exception {
  2. try {
  3. int a = 5/0;
  4. } catch (ArithmeticException e) {
  5. e.printStackTrace();
  6. return "math-exception";
  7. } catch (Exception e){
  8. e.printStackTrace();
  9. return "otherwise-exception";
  10. }
  11. return "success";
  12. }
	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";
		}
		return "success";
	}

这样,在运行中出现ArithmeticException就会跳转到math-exception指定的页面,而其他Exception就会跳转到otherwise-exception指定的页面,如果没有出错,就会跳转到success指定的页面。

在struts.xml的Action中,只要配置好上述三个Result就可以正常运行了。

2:使用Struts2的异常机制

介绍到这里,我们还没有接触Struts2的异常机制,只是把Struts2的异常机制要做的事情,自己用编码实现了一遍。下面,来看看如何使用Struts2的异常机制。

在<action>元素中设置<exception-mapping>元素,可以指定在execute方法抛出指定错误的时候,跳转到哪个指定的页面。

修改上面的代码,使用Struts2的异常机制就不需要自己手动去try-catch了,Action的代码还原为如下所示:

java代码:
  1. public String execute() throws Exception {
  2. int a = 5/0;
  3. return this.SUCCESS;
  4. }
public String execute() throws Exception {
		int a = 5/0;
		return this.SUCCESS;
}

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

java代码:
  1. <action name="helloworldAction" class="cn.javass.action.action.HelloWorldAction">
  2. <exception-mapping result="math-exception" exception="java.lang.ArithmeticException"/>
  3. <exception-mapping result="math-exception" exception="java.lang.Exception"/>
  4. <result name="math-exception">/error.jsp</result>
  5. <result>/s2impl/welcome.jsp</result>
  6. </action>
        <action name="helloworldAction" class="cn.javass.action.action.HelloWorldAction">
        	<exception-mapping result="math-exception" exception="java.lang.ArithmeticException"/>
        	<exception-mapping result="math-exception" exception="java.lang.Exception"/>
            <result name="math-exception">/error.jsp</result>
            <result>/s2impl/welcome.jsp</result>
        </action>

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

这里配置的名称为“math-exception”的Result,指向了web应用根下的error.jsp,在里面只是简单的输出了一句话,示例如下:

java代码:
  1. <%@ page language="java" contentType="text/html; charset=gb2312"
  2. pageEncoding="gb2312"%>
  3. <html>
  4. <head>
  5. <meta http-equiv="Content-Type" content="text/html; charset=gb2312">
  6. <title>Insert title here</title>
  7. </head>
  8. <body>
  9. 对不起,出错了
  10. </body>
  11. </html>
<%@ page language="java" contentType="text/html; charset=gb2312"
    pageEncoding="gb2312"%>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=gb2312">
<title>Insert title here</title>
</head>
<body>
对不起,出错了
</body>
</html>

这样一来,当Action的execute方法抛出错误的时候,如果其<action>元素配置了<exception-mapping>子元素,则会按顺序寻找,找到第一个符合条件的<exception-mapping>元素,跳转到其指定的Result;如果找不到符合条件的<exception-mapping>元素,仍然把错误交给web容器处理。

对比一下,使用了异常机制之后,Action的execute方法跟以前的实现是一样的,不需要自己去try-catch了,而原来对应的多个catch块,实际上都变成了<exception-mapping>的配置。

一般情况下,实际开发中会使用异常机制,可以把重复的catch块提炼到配置文件中,便于统一的配置和维护。

5.5.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>之前,示例如下:

java代码:
  1. <package name="helloworld" extends="struts-default">
  2. <global-results>
  3. <result name="math-exception">/error.jsp</result>
  4. </global-results>
  5. <global-exception-mappings>
  6. <exception-mapping result="math-exception" exception="java.lang.ArithmeticException"/>
  7. <exception-mapping result="math-exception" exception="java.lang.Exception"/>
  8. </global-exception-mappings>
  9. <action name="helloworldAction" class="cn.javass.action.action.HelloWorldAction">
  10. <result>/s2impl/welcome.jsp</result>
  11. </action>
  12. </package>
<package name="helloworld"  extends="struts-default">
    	<global-results>
			<result name="math-exception">/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.action.action.HelloWorldAction">
            <result>/s2impl/welcome.jsp</result>
        </action>
    </package>

对比局部结果和全局结果的查找顺序,可以很容易的理解局部异常映射和全局异常映射的查找顺序。

(1)首先,找自己的<action>元素的内的<exception-mapping >元素是否有匹配的,如果有就执行这个exception的映射配置,如果没有,下一步。

(2)其次,找自己的包里面的全局异常映射,也就是到自己的<action>所在的package中,找<global-exception-mappings >元素内的< exception-mapping >元素,看看是否有匹配的,如果有就执行这个exception的映射配置,如果没有,下一步。

(3)再次,递归的寻找自己的包的父包、祖父包中的全局异常映射是否有匹配的,如果有就执行这个exception的映射配置,如果没有,下一步。

(4)最后,如果上述三种情况都没有的话,则将Exception抛出给Struts2去处理。

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

5.5.3 在页面输出异常信息

在前面的示例中,当Action的execute方法抛出一个异常之后,跳转到指定的页面,也就是error.jsp后,只是简单的输出一句信息,并没有把具体的异常信息展示出来。那么,想要在error.jsp页面上展示Exception的错误信息,该怎么做呢?

可以使用Struts2提供的标签,来输出Exception的错误信息,如下:

  • <s:property value=”exception”/>:仅仅简单打印出exception对象的例外消息。
  • <s:property value=”exceptionStack”/>可以打印出exception的堆栈信息。

在error.jsp页面上使用上面的s标签即可,示例如下:

java代码:
  1. <%@ page language="java" contentType="text/html; charset=gb2312"
  2. pageEncoding="gb2312"%>
  3. <html>
  4. <head>
  5. <meta http-equiv="Content-Type" content="text/html; charset=gb2312">
  6. <title>Insert title here</title>
  7. </head>
  8. <body>
  9. <%@ taglib prefix="s" uri="/struts-tags"%>
  10. <font color=red><b>对不起,出错了,错误信息为:</b></font><br>
  11. <s:property value="exception"/>
  12. <br>
  13. <font color=red><b>错误的堆栈信息为:</b></font><br>
  14. <s:property value="exceptionStack"/>
  15. </body>
  16. </html>
<%@ page language="java" contentType="text/html; charset=gb2312"
    pageEncoding="gb2312"%>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=gb2312">
<title>Insert title here</title>
</head>
<body>
<%@ taglib prefix="s" uri="/struts-tags"%>
<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>

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值