异常映射
我们知道在action的execute方法签名中定义了可以抛出任何类型的异常。至于这个异常抛给了谁,那当然是struts2框架了,如果我们没有设置响应的策略,那么struts2也不会对异常进行处理,又直接抛给web容器了。
如果我们需要Aaction在发生异常时跳转到指定的提示页面,那么我们当然可以在action中使用try..catch语句来返回不同的结果,但是Struts2为我们提供了更加方便的方式,那就是异常映射。我们只需要在配置文件中进行一些配置,就可以省去action中的try。。catch语句块。配置的方式就是在<action>元素中使用<exception-mapping>元素,可以指定在动作方法抛出指定异常时要执行那个result。
<action
name="*User"
class="action.UserAction"
method="{1}">
<result
name="input">/input.jsp</result>
<result
name="success">success.jsp</result>
<result
name="error">/error.jsp</result>
<exception-mapping
result="error"
exception="java.lan.ArithmeticException"></exception-mapping>
</action>
其中exception属性用于指出捕获指定的异常类型,result属性用于指出在捕获到该异常时需要呈现的result。
异常捕获通过exception拦截器来实现,该拦截器位于defaultStack拦截器栈的最顶端,因此能够不会整个调用过程中的异常,exception拦截器对应的实现类为:
com.opensymphony.xwork2.interceptor.ExceptionMappingInterceptor查看其源码:
public String intercept(ActionInvocation invocation) throws Exception {
String result;
try {
result = invocation.invoke();
} catch (Exception e) {
if (isLogEnabled()) {
handleLogging(e);
}
List<ExceptionMappingConfig> exceptionMappings = invocation.getProxy().getConfig().getExceptionMappings();
String mappedResult = this.findResultFromExceptions(exceptionMappings, e);
if (mappedResult != null) {
result = mappedResult;
publishException(invocation, new ExceptionHolder(e));
} else {
throw e;
}
}
return result;
}
protected void publishException(ActionInvocation invocation, ExceptionHolder exceptionHolder) {
invocation.getStack().push(exceptionHolder);
}
可以看到在exception拦截器中使用了try。。catch来捕获整个执行过程中的异常,如果执行过程中没有抛出异常,那么就将Action的执行结果正常返回,如果执行过程中出现了异常,那么就会查找与抛出的异常类型最接近的异常映射,并且将返回在在异常映射中配置的Result。
并且拦截器会将捕获到的异常包装成ExceptionHolder对象并将其压入valueSack。我们在看一下ExceptionHolder类的源码:
public class ExceptionHolder implements Serializable {
private Exception exception;
/**
* Holds the given exception
*
* @param exception the exception to hold.
*/
public ExceptionHolder(Exception exception) {
this.exception = exception;
}
/**
* Gets the holded exception
*
* @return the holded exception
*/
public Exception getException() {
return this.exception;
}
/**
* Gets the holded exception stacktrace using {@link Exception#printStackTrace()}.
*
* @return stacktrace
*/
public String getExceptionStack() {
String exceptionStack = null;
if (getException() != null) {
StringWriter sw = new StringWriter();
PrintWriter pw = new PrintWriter(sw);
try {
getException().printStackTrace(pw);
exceptionStack = sw.toString();
}
finally {
try {
sw.close();
pw.close();
} catch (IOException e) {
// ignore
}
}
}
return exceptionStack;
}
}
可以看到,在该类中将exception的trackStack转换成字符串存放在exceptionStack变量中。在struts2中要想使用OGNL调用Action类的某个属性,那么我们必须保证该属性有对应的get方法。那么实际上的调用全部是通过调用get方法来获取的,至于到底Action中是否存在对应的变量以及变量的名字是否和get方法对应其实并不影响,真正起作用的只是get方法。那么在这个ExceptionHolder类中有两个get方法,一个是getException,另一个是getExceptionStack,那么也就是说我们在使用OGNL调用该类的属性时,相当于存在两个属性:exception和exceptionStack。因为这个ExceptionHolder对象已经被放入了valueStack的顶部,也就是说,我们可以在我们配置的异常结果页面通过OGNL来访问这两个属性的内容:
<s:propertyvalue="%{exception.message}"/>
<s:propertyvalue="%{exceptionStack}"/>
PreResultListenner
不管处于什么目的,有时候我们需要在Action方法执行完毕,但是在执行Result之前能够做点什么。那么怎么实现这个功能呢?这时PreResultListener就派上用场了。一看它的名字就知道它是一个Listenner,那么它监听的事件就是Action方法执行完毕,将要执行Result。具体这个时间我们并不需要关注,struts2会自动分发这个事件,并触发我们的监听器。我们要做的就是实现这个Listenner,并把它注册到Action上。
首先我们需要实现PreResultLisenner这个接口:
public class MyPreResultListennerImpl implements PreResultListener {
public void beforeResult(ActionInvocation invocation, String resultCode) {
System.out.println("正在执行"+resultCode+"结果执行之前的操作...");
}
}
我们的实现类所做的操作就打印一句话,用于我们判断执行的先后顺序。
然后我们在Result视图中也打印一句话:
<%@ page
language="java"
import="java.util.*"
pageEncoding="UTF-8"%>
<!DOCTYPE
HTML PUBLIC
"-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<title>PreResultListenner Demo Result</title>
</head>
<body>
<%
System.out.println("结果页面已经被执行....");
%>
</body>
</html>
我们在Action的excute方法中对我们的Listenner进行注册:
public class HelloWorld extends ActionSupport {
private String userName;
public String getUserName() {
return userName;
}
public void setUserName(String userName) {
this.userName = userName;
}
public String execute() throws Exception {
ActionContext.getContext().getActionInvocation().addPreResultListener(
new MyPreResultListennerImpl());
return "success";
}
}
在struts.xml配置helloworld动作,并配置相应的Result,然后我们在浏览器中访问一下helloworld动作,页面执行完毕之后查看控制台的输出:
正在执行success结果执行之前的操作...
结果页面已经被执行....
表明在执行Result之前确实先执行了我们的Listenner。
自定义Result
自定义Result就是我们自己开发Result,不实用Struts2内建的Result Type,实际使用中我们几乎不会用到自定义Result,strut2内建的Result Type已经够我们使用了。这里就当时简单的了解一下吧。
要实现自定义Result,其步骤如下:
(1)定义一个类,实现com.opensymphony.xwork2.Result接口
(2)在struts.xml中,在<package>元素中使用<result-types>元素声明我们的Result Type
(3)在Action中的<result>元素中将type属性指定为我们在(2)中声明的Result Type
下面动手做一个简单的实例:
public class MyResult implements Result {
public void execute(ActionInvocation invocation) throws Exception {
System.out.println("要执行的reuslt为:" + invocation.getResultCode());
}
}
这里我只是简单的打印出一句话,当然,实际要实现一个Result需要做的事情很多,有兴趣的可以参看struts2内建的Result Type的实现。
struts.xml
<package
name="default"
namespace="/"
extends="struts-default">
<result-types>
<result-type
name="myresult"class="action.MyResult"></result-type>
</result-types>
<action
name="hello"
class="action.HelloWorld">
<result
name="input">/input.jsp</result>
<result
name="success"
type="myresult">/success.jsp</result>
</action>
</package>
我在浏览器中测试,由于我们result实现中没有任何执行输出到浏览器的功能,因此浏览中无任何输出,查看控制台,输出如下:
要执行的reuslt为:success
到这里,我们自定义的Result就完成了。从这个例子中我们也可以看出,要实现自定义的Result其实不难,难的就是我们怎么去呈现这些数据,那么我们就必须使用一种视图呈现技术,实际Result也就是对视图呈现技术的一中包装(或者说调用吧)。
分享到:
相关推荐
struts2学习笔记总结
Struts2学习笔记,介绍了struts2的基础部分
struts2学习笔记,非本人所写,但有学习的价值,总结的很好,分享一个!
这是学习struts2时记得重点笔记,包括了一些原理,ognl语句的编写,以及如何设置拦截器等等一些基本知识,起到复习和巩固的作用
struts2学习笔记struts2学习笔记struts2学习笔记
struts2学习笔记3数据类型转换struts2学习笔记3数据类型转换struts2学习笔记3数据类型转换struts2学习笔记3数据类型转换struts2学习笔记3数据类型转换struts2学习笔记3数据类型转换struts2学习笔记3数据类型转换
本人学习struts2的笔记,希望大家可以多多学习以后共同交流
2)把struts2框架的配置文件struts.xml复制粘贴到项目中的src下面(同时也可以把log4j.properties放到src下) 在这里我们主要是要的这个struts.xml文件的中的声明部 分,以前写这个文件的话可以直接复制粘贴过来,没有写...
namespace :对应与项目名称后面的"/"(例如Struts2_0100_Introduction后面的"/") (http://localhost:8080/Struts2_0100_Introduction/) 四、 标签 是用来解决重名的问题,例如当系统的前台和后台都有一个action...
structs2很详细的学习笔记,structs2的建造,工作原理,例子,逐步讲解,纯文字的
struts2四天的学习笔记。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。
02 Struts2-Result 19 一、 Result类型 (type) 19 二、 全局结果集(Globle Result) 20 三、 动态的结果集(dynamic result) 21 四、 带参数的结果集 21 五、 Result总结 22 六、 项目经理: 22 03 OGNL表达式语言 23 ...
个人收藏,纯属备份作用,做个记录,方便需要时候查看
Struts2 学习笔记.doc,Struts2 学习笔记.doc
struts2学习笔记三