• struts2-invocation


    [转载]       

    “将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方法中相关代码:
         

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



       2. 通过ActionInvocation.invoke方法调用Action实现时,执行Interceptor:
           下面是DefaultActionInvocation中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;
        }

        



    所有的拦截器都必须实现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;
    }


        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);
    }

    }

    }

    }



    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);      //压栈
    }
    ……


    旁白:Servlet 2.3规范中引入的Filter 算是拦截器的一个典型实现,它在Servlet执行之前被触发,对输入参数进行处理之后,再将工作流程传递给对应的Servlet。

  • 相关阅读:
    brew
    hbase
    YARN常见问题以及解决方案
    mybatis中foreach collection三种用法
    mysql按分隔符输出多行
    mysql DATETIME
    iis 之给网站添加MIME映射
    VS2019专业版和企业版激活密钥
    ViewData对于从后台传list到前台的使用
    找出每组数据中不同distinct
  • 原文地址:https://www.cnblogs.com/wangjianbg/p/3555584.html
Copyright © 2020-2023  润新知