webwork拦截器interceptor 之 ActionInvocation

“将Web页面中的输入元素封装为一个(请求)数据对象”,这个对象就是ActionInvocation类型. 
对于Xwork 而言,前端的Webwork 组件为其提供的是一个Map 类型的数据结构。而Action面向的却是Model对象所提供的数据结构。在何时、何处对这两种不同的数据结构进行转换? 
写一个辅助类完成这样的工作,并在每次Action 调用之前由框架代码调用他完成转换工作。 
Xwork 通过Interceptor 实现了这一步骤,从而我们可以根据需要,灵活的配置所需的Interceptor。从而为Action提供可扩展的预处理、后处理过程。

ActionInvocation 是Xworks 中Action 调度的核心。而对Interceptor 的调度,也正是由ActionInvocation负责。 
ActionInvocation 是一个接口, 而DefaultActionInvocation 则是Webwork 对ActionInvocation的默认实现。

Interceptor 的调度流程大致如下:

1. ActionInvocation初始化时,根据配置,加载Action相关的所有Interceptor。

参见ActionInvocation.init方法中相关代码:

Java代码:

private void init() throws Exception ...{    
……    
List interceptorList = new   
ArrayList(proxy.getConfig().getInterceptors());    
interceptors

2. 通过ActionInvocation.invoke方法调用Action实现时,执行Interceptor: 
下面是DefaultActionInvocation中Action调度代码: 
Java代码:

public String <SPAN class=undefined>invoke</SPAN>() 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 = <SPAN class=undefined>invoke</SPAN>Action(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:

Java代码:

public abstract class AroundInterceptor implements Interceptor    
...{    
    protected Log log = LogFactory.getLog(this.getClass());    
        
    public void destroy() ...{    
    }    
        
    public void init() ...{    
    }    
        
    public String intercept(<SPAN class=hilite1>ActionInvocation</SPAN> invocation) throws Exception ...{    
    String result = null;    
    before(invocation);    
    result = invocation.<SPAN class=undefined>invoke</SPAN>();    
    after(invocation, result);    
    return result;    
    }    
        
    protected abstract void after    
    (<SPAN class=hilite1>ActionInvocation</SPAN> <SPAN class=hilite1>actioninvocation</SPAN>, String string) throws Exception;    
        
    protected abstract void before(<SPAN class=hilite1>ActionInvocation</SPAN> <SPAN class=hilite1>actioninvocation</SPAN>)    
    throws Exception;    
}

AroundInterceptor.invoke 方法中,调用了参数invocation的invoke 方法。

最后,结合最常用的ParametersInterceptor,看看Xwork 是如何通过Interceptor,将Webwork传入的Map类型数据结构,转换为Action所需的Java 模型对象。

ParametersInterceptor.java: 
Java代码:

public class ParametersInterceptor extends AroundInterceptor ...{    
protected void after(<SPAN class=hilite1>ActionInvocation</SPAN> dispatcher, String result)    
throws Exception ...{    
}    
protected void before(<SPAN class=hilite1>ActionInvocation</SPAN> 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在初始化的时候已经预先完成了压栈工作,如DefaultActionInvocation.init方法中代码所示:

private void init() throws Exception { 
Map contextMap = createContextMap(); 
createAction(); 
if (pushAction) { 
stack.push(action); //压栈 

…… 
}

时间: 2024-10-14 07:13:19

webwork拦截器interceptor 之 ActionInvocation的相关文章

详述 Spring MVC 框架中拦截器 Interceptor 的使用方法

1 前言 昨天新接了一个需要,"拦截 XXX,然后 OOO",好吧,说白了就是要用拦截器干点事(实现一个具体的功能).之前,也在网络上搜了很多关于Interceptor的文章,但感觉内容都大同小异,而且知识点零零散散,不太方便阅读.因此,正好借此机会,整理一篇关于拦截器的文章,在此分享给大家,以供大家参考阅读. 2 拦截器 2.1 概念 Java 里的拦截器是动态拦截 action 调用的对象.它提供了一种机制可以使开发者可以定义在一个 action 执行的前后执行的代码,也可以在一个

Struts拦截器Interceptor

Struts2 拦截器 [Interceptor] 拦截器的工作原理如上图,每一个Action请求都包装在一系列的拦截器的内部.拦截器可以在Action执行直线做相似的操作也可以在Action执行直后做回收操作. 每一个Action既可以将操作转交给下面的拦截器,Action也可以直接退出操作返回客户既定的画面. 如何自定义一个拦截器? 自定义一个拦截器需要三步: 1 自定义一个实现Interceptor接口(或者继承自AbstractInterceptor)的类. 2 在strutx.xml中

Flume-NG源码阅读之SourceRunner,及选择器selector和拦截器interceptor的执行

在AbstractConfigurationProvider类中loadSources方法会将所有的source进行封装成SourceRunner放到了Map<String, SourceRunner> sourceRunnerMap之中.相关代码如下: 1 Map<String, String> selectorConfig = context.getSubProperties( 2 BasicConfigurationConstants.CONFIG_SOURCE_CHANNE

Kafka producer拦截器(interceptor)

Producer拦截器(interceptor)是个相当新的功能,它和consumer端interceptor是在Kafka 0.10版本被引入的,主要用于实现clients端的定制化控制逻辑. 对于producer而言,interceptor使得用户在消息发送前以及producer回调逻辑前有机会对消息做一些定制化需求,比如修改消息等.同时,producer允许用户指定多个interceptor按序作用于同一条消息从而形成一个拦截链(interceptor chain).Intercetpor

struts2拦截器interceptor的三种配置方法

struts2拦截器interceptor的三种配置方法方法1. 普通配置法 <struts>     <package name="struts2" extends="struts-default">         <interceptors>             <interceptor name="myInterceptor" class="edu.hust.interceptor.

Flume 拦截器(interceptor)详解

flume 拦截器(interceptor)1.flume拦截器介绍拦截器是简单的插件式组件,设置在source和channel之间.source接收到的事件event,在写入channel之前,拦截器都可以进行转换或者删除这些事件.每个拦截器只处理同一个source接收到的事件.可以自定义拦截器.2.flume内置的拦截器 2.1 时间戳拦截器flume中一个最经常使用的拦截器 ,该拦截器的作用是将时间戳插入到flume的事件报头中.如果不使用任何拦截器,flume接受到的只有message.

五 、 Kafka producer 拦截器(interceptor) 和 六 、Kafka Streaming案例

五 Kafka producer 拦截器(interceptor) 5.1 拦截器原理 Producer 拦截器(interceptor)是在 Kafka 0.10 版本被引入的,主要用于实现 clients 端的定 制化控制逻辑. 对于 producer 而言,interceptor 使得用户在消息发送前以及 producer 回调逻辑前有机会 对消息做一些定制化需求,比如修改消息等.同时,producer 允许用户指定多个 interceptor 按序作用于同一条消息从而形成一个拦截链(in

拦截器interceptor

拦截器interceptor 配置 <mvc:interceptors> <mvc:interceptor> <!--/**回处理/后面的所有请求--> <mvc:mapping path="/**"/> <bean class="cn.pinked.config.MyInterceptor"/> </mvc:interceptor> </mvc:interceptors> 拦截器

Struts2自定义拦截器Interceptor以及拦截器登录实例

1.在Struts2自定义拦截器有三种方式: -->实现Interceptor接口 public class QLInterceptorAction implements Interceptor{ private static final long serialVersionUID = 1L; public void destroy() { } public void init() {} public String intercept(ActionInvocation arg0) throws