“将Web页面中的输入元素封装为一个(请求)数据对象”,这个对象就是
ActionInvocation
类型.
对于Xwork 而言,前端的Webwork 组件为其提供的是一个Map 类型的数据结构。而Action面向的却是Model对象所提供的数据结构。在何时、何处对这两种不同的数据结构进行转换?
写一个辅助类完成这样的工作,并在每次Action 调用之前由框架代码调用他完成转换工作。
Xwork 通过Interceptor 实现了这一步骤,从而我们可以根据需要,灵活的配置所需的Interceptor。从而为Action提供可扩展的预处理、后处理过程。
ActionInvocation
是Xworks 中Action 调度的核心。而对Interceptor 的调度,也正是由
ActionInvocation
负责。
ActionInvocation
是一个接口, 而Default
ActionInvocation
则是Webwork 对
ActionInvocation
的默认实现。
Interceptor 的调度流程大致如下:
1.
ActionInvocation
初始化时,根据配置,加载Action相关的所有Interceptor。
参见
ActionInvocation
.init方法中相关代码:
- private
void
init()
throws
Exception ...{
- ……
- List interceptorList = new
- ArrayList(proxy.getConfig().getInterceptors());
- interceptors = interceptorList.iterator();
- }
private void init() throws Exception ...{
……
List interceptorList = new
ArrayList(proxy.getConfig().getInterceptors());
interceptors = interceptorList.iterator();
}
2. 通过
ActionInvocation
.invoke方法调用Action实现时,执行Interceptor:
下面是Default
ActionInvocation
中Action调度代码:
- public
String invoke()
throws
Exception ...{
- if
(executed)
- throw
new
IllegalStateException(
"Action has already executed"
);
- if
(interceptors.hasNext()) ...{
- Interceptor interceptor = (Interceptor) interceptors.next();
- resultCode = interceptor.intercept(this
);
- } else
- resultCode = invokeAction(getAction(), proxy.getConfig());
- if
(!executed) ...{
- if
(preResultListeners !=
null
) ...{
- Iterator iterator = preResultListeners.iterator();
- while
(iterator.hasNext()) ...{
- PreResultListener listener
- = (PreResultListener) iterator.next();
- listener.beforeResult(this
, resultCode);
- }
- }
- if
(proxy.getExecuteResult())
- executeResult();
- executed = true
;
- }
- return
resultCode;
- }
public String invoke() throws Exception ...{
if (executed)
throw new IllegalStateException("Action has already executed");
if (interceptors.hasNext()) ...{
Interceptor interceptor = (Interceptor) interceptors.next();
resultCode = interceptor.intercept(this);
} else
resultCode = invokeAction(getAction(), proxy.getConfig());
if (!executed) ...{
if (preResultListeners != null) ...{
Iterator iterator = preResultListeners.iterator();
while (iterator.hasNext()) ...{
PreResultListener listener
= (PreResultListener) iterator.next();
listener.beforeResult(this, resultCode);
}
}
if (proxy.getExecuteResult())
executeResult();
executed = true;
}
return resultCode;
}
所有的拦截器都必须实现Interceptor 接口。
public interface Interceptor {
void destroy();
void init();
String intercept(
ActionInvocation
invocation) throws Exception;
}
在Interceptor 实现中,抽象实现AroundInterceptor得到了最广泛的应用(扩展),它增加了预处理(before)和后处理(after)方法的定义。
AroundInterceptor.java:
- public
abstract
class
AroundInterceptor
implements
Interceptor
- ...{
- protected
Log log = LogFactory.getLog(
this
.getClass());
-
- public
void
destroy() ...{
- }
-
- public
void
init() ...{
- }
-
- public
String intercept(ActionInvocation
invocation)
throws
Exception ...{
- String result = null
;
- before(invocation);
- result = invocation.invoke();
- after(invocation, result);
- return
result;
- }
-
- protected
abstract
void
after
- (ActionInvocation
actioninvocation
, String string) throws
Exception;
-
- protected
abstract
void
before(ActionInvocation
actioninvocation
)
- throws
Exception;
- }
public abstract class AroundInterceptor implements Interceptor
...{
protected Log log = LogFactory.getLog(this.getClass());
public void destroy() ...{
}
public void init() ...{
}
public String intercept(ActionInvocation
invocation) throws Exception ...{
String result = null;
before(invocation);
result = invocation.invoke();
after(invocation, result);
return result;
}
protected abstract void after
(ActionInvocation
actioninvocation
, String string) throws Exception;
protected abstract void before(ActionInvocation
actioninvocation
)
throws Exception;
}
AroundInterceptor.invoke 方法中,调用了参数invocation的invoke 方法。
最后,结合最常用的ParametersInterceptor,看看Xwork 是如何通过Interceptor,将Webwork传入的Map类型数据结构,转换为Action所需的Java 模型对象。
ParametersInterceptor.java:
- public
class
ParametersInterceptor
extends
AroundInterceptor ...{
- protected
void
after(ActionInvocation
dispatcher, String result)
- throws
Exception ...{
- }
- protected
void
before(ActionInvocation
invocation)
throws
Exception
- ...{
- if
(!(invocation.getAction()
instanceof
NoParameters)) ...{
- final
Map parameters =
- ActionContext.getContext().getParameters(); ⑴
- if
(log.isDebugEnabled()) ...{
- log.debug("Setting params "
+ parameters);
- }
- ActionContext invocationContext =
- invocation.getInvocationContext();
- try
...{
- invocationContext.put(
- InstantiatingNullHandler.CREATE_NULL_OBJECTS,
- Boolean.TRUE);
- invocationContext.put(
- XWorkMethodAccessor.DENY_METHOD_EXECUTION,
- Boolean.TRUE);
- invocationContext.put(
- XWorkConverter.REPORT_CONVERSION_ERRORS,
- Boolean.TRUE);
- if
(parameters !=
null
) ...{
- final
OgnlValueStack stack =
- ActionContext.getContext().getValueStack(); ⑵
- for
(Iterator iterator =parameters.entrySet().iterator();
- iterator.hasNext();
- ) ...{
- Map.Entry entry = (Map.Entry) iterator.next();
- stack.setValue( ⑷
- entry.getKey().toString(),
- entry.getValue());
- }
- }
- } finally
...{
- invocationContext.put(
- InstantiatingNullHandler.CREATE_NULL_OBJECTS,
- Boolean.FALSE);
- invocationContext.put(
- XWorkMethodAccessor.DENY_METHOD_EXECUTION,
- Boolean.FALSE);
- invocationContext.put(
- XWorkConverter.REPORT_CONVERSION_ERRORS,
- Boolean.FALSE);
- }
- }
- }
- }
public class ParametersInterceptor extends AroundInterceptor ...{
protected void after(ActionInvocation
dispatcher, String result)
throws Exception ...{
}
protected void before(ActionInvocation
invocation) throws Exception
...{
if (!(invocation.getAction() instanceof NoParameters)) ...{
final Map parameters =
ActionContext.getContext().getParameters(); ⑴
if (log.isDebugEnabled()) ...{
log.debug("Setting params " + parameters);
}
ActionContext invocationContext =
invocation.getInvocationContext();
try ...{
invocationContext.put(
InstantiatingNullHandler.CREATE_NULL_OBJECTS,
Boolean.TRUE);
invocationContext.put(
XWorkMethodAccessor.DENY_METHOD_EXECUTION,
Boolean.TRUE);
invocationContext.put(
XWorkConverter.REPORT_CONVERSION_ERRORS,
Boolean.TRUE);
if (parameters != null) ...{
final OgnlValueStack stack =
ActionContext.getContext().getValueStack(); ⑵
for (Iterator iterator =parameters.entrySet().iterator();
iterator.hasNext();
) ...{
Map.Entry entry = (Map.Entry) iterator.next();
stack.setValue( ⑷
entry.getKey().toString(),
entry.getValue());
}
}
} finally ...{
invocationContext.put(
InstantiatingNullHandler.CREATE_NULL_OBJECTS,
Boolean.FALSE);
invocationContext.put(
XWorkMethodAccessor.DENY_METHOD_EXECUTION,
Boolean.FALSE);
invocationContext.put(
XWorkConverter.REPORT_CONVERSION_ERRORS,
Boolean.FALSE);
}
}
}
}
ParametersInterceptor 扩展了抽象类AroundInterceptor。并在其预处理方法(before)中实现了数据的转换。
数据转换的过程并不复杂:
⑴ 首先由ActionContext获得Map型的参数集parameters。
⑵ 由ActionContext获得值栈(OgnlValueStack)。
⑶ 遍历parameters中的各项数据。
⑷ 通过OgnlValueStack,根据数据的键值,为Model 对象填充属性数据。
OgnlValueStack 是http://www.ognl.org4提供的一套可读写对象属性的类库
上面的代码中并没有发现将Model对象入栈的部分,是由于
ActionInvocation
在初始化的时候已经预先完成了压栈工作,如Default
ActionInvocation
.init方法中代码所示:
private void init() throws Exception {
Map contextMap = createContextMap();
createAction();
if (pushAction) {
stack.push(action); //压栈
}
……
}
旁白:Servlet 2.3规范中引入的Filter 算是拦截器的一个典型实现,它在Servlet执行之前被触发,对输入参数进行处理之后,再将工作流程传递给对应的Servlet。
相关推荐
07 Struts 2的基石——拦截器(Interceptor) 08 在Struts 2中实现IoC 09 在Struts 2中实现文件上传 10 在Struts 2中实现CRUD 11 Struts 2中的OGNL 12 trus 2的新表单标志的使用 13 Struts 2与AJAX
Struts 2.0系列(MAX),pdf格式,全...Struts 2的基石——拦截器(Interceptor) 在Struts 2中实现IoC 在Struts 2中实现文件上传 在Struts 2中实现CRUD Struts 2中的OGNL Strus 2的新表单标志的使用 Struts 2与AJAX
07 Struts 2的基石——拦截器(Interceptor) 08 在Struts 2中实现IoC 09 在Struts 2中实现文件上传 10 在Struts 2中实现CRUD 11 Struts 2中的OGNL 12 trus 2的新表单标志的使用 13 Struts 2与AJAX Struts2中用...
07 Struts 2的基石——拦截器(Interceptor) 08 在Struts 2中实现IoC 09 在Struts 2中实现文件上传 10 在Struts 2中实现CRUD 11 Struts 2中的OGNL 12 Struts 2的新表单标志的使用 13 Struts 2与AJAX
· 引入拦截器: Struts 2为拦截器(interceptor)提供了全面支持。拦截器可在Action类执行前后加以执行。拦截器经配置后,可以把工作流程或者验证等常见功能作用到请求上。所有请求通过一组拦截器传送,之后再发送到...
很好的struts2入门教程... ·拦截器(Interceptor) ·Struts 2中实现IoC ·Struts 2中实现文件上传 ·Struts 2中的OGNL ·Strus 2的新表单标签的使用 ·Struts 2与AJAX ·Struts2分页 ·完全Struts's Tiles入门
还有登录拦截器:com.light.framework.interceptor 字符集过滤器:com.light.framework.filter 项目字符集请用UTF-8 com.light.framework包中还有些小东西 自己看看吧 我是用MyEclipse6.0开发的(MyEclipse...
如果Action中引用了其它的拦截器 默认的拦截器将无效 --> <default-interceptor-ref name="mystack"></default-interceptor-ref> <!-- 全局results配置 --> <result name="input">/error.jsp ...
118 8.3.5 Struts2配置文件 119 8.4 Action的配置方式 121 8.4.1 动态方法调用 121 8.4.2 设置action元素的method属性 122 8.4.3 使用通配符配置action 122 8.4.4 默认action 123 8.5 拦截器Interceptor 123 8.5.1 ...