前奏:
•在使用 Struts作为前端的企业级应用程序时把Action 和Model 清晰地隔离开是有必要的:有些 Action类不代表任何Model对象,它们的功能仅限于提供显示服务
具体介绍:
ModelDriven 拦截器:当用户触发 add 请求时, ModelDriven 拦截器将调用 EmployeeAction 对象的 getModel() 方法, 并把返回的模型(Employee实例)压入到 ValueStack 栈.
接下来 Parameters 拦截器将把表单字段映射到 ValueStack 栈的栈顶对象的各个属性中. 因为此时 ValueStack 栈的栈顶元素是刚被压入的模型(Employee)对象, 所以该模型将被填充. 如果某个字段在模型里没有匹配的属性, Param 拦截器将尝试 ValueStack 栈中的下一个对象,源代码如下:
@Override
public String intercept(ActionInvocation invocation) throws Exception {
Object action = invocation.getAction();
if (action instanceof ModelDriven) {
ModelDriven modelDriven = (ModelDriven) action;
ValueStack stack = invocation.getStack();
Object model = modelDriven.getModel();
if (model != null) {
stack.push(model);
}
if (refreshModelBeforeResult) {
invocation.addPreResultListener(new RefreshModelBeforeResult(modelDriven, model));
}
}
return invocation.invoke();
}
Preparable 拦截器:Struts 2.0 中的 modelDriven 拦截器负责把 Action 类以外的一个对象压入到值栈栈顶,而 prepare 拦截器负责准备为 getModel() 方法准备 model;
具体用法:
1:若 Action 实现 Preparable 接口,则 Action 方法需实现 prepare() 方法:2:PrepareInterceptor 拦截器将调用 prepare() 方法,prepareActionMethodName()方法 或 prepareDoActionMethodName ()方法 3:PrepareInterceptor 拦截器根据 firstCallPrepareDo 属性决定获取 prepareActionMethodName 、prepareDoActionMethodName的顺序。默认情况下先获取 prepareActionMethodName (), 如果没有该方法,就寻找prepareDoActionMethodName()。如果找到对应的方法就调用该方法
PrepareInterceptor 拦截器会根据 alwaysInvokePrepare 属性决定是否执行prepare()方法;源代码如下:
@Override
public String doIntercept(ActionInvocation invocation) throws Exception {
Object action = invocation.getAction();
if (action instanceof Preparable) {
try {
String[] prefixes;
if (firstCallPrepareDo) {
prefixes = new String[] {ALT_PREPARE_PREFIX, PREPARE_PREFIX};
} else {
prefixes = new String[] {PREPARE_PREFIX, ALT_PREPARE_PREFIX};
}
PrefixMethodInvocationUtil.invokePrefixMethod(invocation, prefixes);
}
catch (InvocationTargetException e) {
/*
* The invoked method threw an exception and reflection wrapped it
* in an InvocationTargetException.
* If possible re-throw the original exception so that normal
* exception handling will take place.
*/
Throwable cause = e.getCause();
if (cause instanceof Exception) {
throw (Exception) cause;
} else if(cause instanceof Error) {
throw (Error) cause;
} else {
/*
* The cause is not an Exception or Error (must be Throwable) so
* just re-throw the wrapped exception.
*/
throw e;
}
}
if (alwaysInvokePrepare) {
((Preparable) action).prepare();
}
}
开发中一般要将两个杰克联合起来进行使用,才能发挥更好的效果。