读书人

struts2 18拦截器详解(7)

发布时间: 2013-11-01 14:43:02 作者: rapoo

struts2 18拦截器详解(七)

ChainingInterceptor


该拦截器处于defaultStack第六的位置,其主要功能是复制值栈(ValueStack)中的所有对象的所有属性到当前正在执行的Action中,如果说ValueStack中没有任何对象的话,该拦截器不会干任何事情,看到这个拦截器的名称,大家应该会想到有一种chain类型的Result,该拦截器主要就是针对chain类型Result起作用的,因为我们有可能在chain链后面的Action用到前面Action的属性,所以struts2提供了该拦截器来实现这个功能。当然我们也可以让chain链中的某个Action属性不复制到正在执行的Action中,只要chain链中的Action实现com.opensymphony.xwork2.Unchainable接口,这个Action中的属性就不会复制到当前正在执行的Action中了。下面我们看一个该拦截器的源码:

public void copy(Object from, Object to, Map<String, Object> context, Collection<String> exclusions, Collection<String> inclusions) {//省略...    PropertyDescriptor[] fromPds;    PropertyDescriptor[] toPds;    try {        fromPds = getPropertyDescriptors(from);//获取源对象(要被复制属性的对象)的属性描述符        toPds = getPropertyDescriptors(to);//获目标对象(当前正在执行的Action对象)的属性描述符    } catch (IntrospectionException e) {        LOG.error("An error occured", e);        return;    }    Map<String, PropertyDescriptor> toPdHash = new HashMap<String, PropertyDescriptor>();    for (PropertyDescriptor toPd : toPds) {        toPdHash.put(toPd.getName(), toPd);//将目标对象属性描述符放到一个HashMap中    }//迭代获取源对象属性描述符    for (PropertyDescriptor fromPd : fromPds) {        if (fromPd.getReadMethod() != null) {//当前属性的读方法不为空            boolean copy = true;            if (exclusions != null && exclusions.contains(fromPd.getName())) {            //如果当前属性包含在exclusions集合中则不复制                copy = false;            } else if (inclusions != null && !inclusions.contains(fromPd.getName())) {            //如果配置了inclusions,而当前属性又不包含在inclusions集合中则不复制            //如果没有配置inclusions,则只要不包含在exclusions就会复制                copy = false;            }            if (copy == true) {//如果当前属性需要复制                PropertyDescriptor toPd = toPdHash.get(fromPd.getName());//获取目标对象相应的属性描述符                if ((toPd != null) && (toPd.getWriteMethod() != null)) {//如果属性描述符存在且其写方法不为空则进行复制                    try {                        Object expr = compile(fromPd.getName());                        Object value = Ognl.getValue(expr, contextFrom, from);                        Ognl.setValue(expr, contextTo, to, value);//真正复制属性的代码                    } catch (OgnlException e) {                        // ignore, this is OK                    }                }            }        }    }}


至此,该拦截器要复制哪些属性,要复制哪些对象的属性,以及复制属性的具体规则已经讲解完毕了,最后一句:Ognl.setValue(expr, contextTo, to, value);
真正复制属性的代码已经涉及到OGNL内部的实现机制,这是很复杂的,但对于理解该拦截器来说不是很重要,这里就不说了,有兴趣的可自行研究。

现在回到intercept方法,当属性复制完成后调用invocation.invoke();继续执行下一个拦截器......

读书人网 >编程

热点推荐