至于action是的创建则是由actionproxy来完成的,来看一段简要的程序调用
actionproxy proxy = actionproxyfactory.getfactory().createactionproxy(namespace, actionname, extracontext);
request.setattribute(servletactioncontext.webwork_valuestack_key, proxy.getinvocation().getstack()); //调用actioninvocation
proxy.execute();
其实 actionproxy是一个接口,而actionproxyfactory则是一个抽象类,他们都是通过一个defaultactionproxy和defaultactionproxyfactory来完成操作的,且actionproxy将调用actioninvocation接口,由defaultactioninvocation初始化的时候读取配置,然后由invoke()方法来完成action的调用及一些在action被调用之前的interceptor的操作.下面是关于defaultactioninvocation的初始化和调用代码.
public class defaultactioninvocation implements actioninvocation {
private void init() throws exception {
map contextmap = createcontextmap();
createaction(); //加载action
if (pushaction) {
stack.push(action);
}
invocationcontext = new actioncontext(contextmap);
invocationcontext.setname(proxy.getactionname());
// get a new list so we dont get problems with the iterator if someone changes the list
list interceptorlist = new arraylist(proxy.getconfig().getinterceptors()); //获取配置
interceptors = interceptorlist.iterator();
}
public string invoke() throws exception {
if (executed) {
throw new illegalstateexception("action has already executed");
}
//这里是执行拦截器的操作, 注: 拦截器本身就是aop的一个特殊实现,servlet2.3 中filter就是一个特例啊
if (interceptors.hasnext()) {
interceptor interceptor = (interceptor) interceptors.next();
resultcode = interceptor.intercept(this);
} else {
resultcode = invokeaction(getaction(), proxy.getconfig());
}
// this is needed because the result will be executed, then control will return to the interceptor, which will
// return above and flow through again
if (!executed) {
if (preresultlisteners != null) {
for (iterator iterator = preresultlisteners.iterator();
iterator.hasnext();) {
preresultlistener listener = (preresultlistener) iterator.next();
listener.beforeresult(this, resultcode);
}
}
// now execute the result, if were supposed to
if (proxy.getexecuteresult()) {
executeresult();
}
executed = true;
}
…
}
下面再来说说interceptor 的实现结构,刚开始我以为xwork1.x中interceptor 应该是从filter中继承下来的,后来看了源码,原来我的想法不对,想想也的确是不需要,也不应该从filter下继承,因为filter就是servlet2.3的一个api,而xwork1.x设计目的就是要脱离servlet api,且interceptor的实现并非是少了filter就不行,只是我们有了filter将会来的更加方便!
对于webwork2.x中的所有的拦截器,他们都有一个公共的接口interceptor,在它当中定义了拦截器的一些基本操作方法,然后有一个aroundinterceptor抽象类,实现了该接口, aroundinterceptor的作用是组合拦截器的调用顺序,代码如下:
public string intercept(actioninvocation invocation) throws exception {
string result = null;
before(invocation); //这里是用于组合调用顺序
result = invocation.invoke();
after(invocation, result);
return result;
}
至于将map 中的数据转换到我们的vo中,是通过parametersinterceptor拦截器来完成操作的,这个拦截器是一个真正的实现类,他从aroundinterceptor抽象类下面继承
public class parametersinterceptor extends aroundinterceptor {
//~ methods ////////////////////////////////////////////////////////////////
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();
//用于获取map 结构中的parameters
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();
//用于获取ognlvaluestack操作,这个package没看过,具体听夏昕说是一套可读写对象属性的的类库,功能有些类似与jakarta commons beanutils ,及spring bean wrapper
for (iterator iterator = parameters.entryset().iterator();
//遍历parameters中的信息
iterator.hasnext();) {
map.entry entry = (map.entry) iterator.next();
string name = entry.getkey().tostring();
//填充vo信息
if (acceptablename(name)) {
object value = entry.getvalue();
stack.setvalue(name, value);
}
}
}
} 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);
}
}
}
protected boolean acceptablename(string name) {
if (name.indexof(=) != -1 || name.indexof(,) != -1 || name.indexof(#) != -1) {
return false;
} else {
return true;
}
}
}
