`

struts2.0 中有关拦截器Interceptor相关知识

阅读更多

008 - 05 - 27

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代码 复制代码
  1. private   void  init()  throws  Exception ...{  
  2. ……  
  3. List interceptorList = new   
  4. ArrayList(proxy.getConfig().getInterceptors());  
  5. interceptors = interceptorList.iterator();  
  6. }  
private void init() throws Exception ...{
……
List interceptorList = new
ArrayList(proxy.getConfig().getInterceptors());
interceptors = interceptorList.iterator();
}


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

Java代码 复制代码
  1. public  String invoke()  throws  Exception ...{  
  2.     if  (executed)  
  3.         throw   new  IllegalStateException( "Action has already executed" );  
  4.     if  (interceptors.hasNext()) ...{  
  5.         Interceptor interceptor = (Interceptor) interceptors.next();  
  6.         resultCode = interceptor.intercept(this );  
  7.     } else   
  8.         resultCode = invokeAction(getAction(), proxy.getConfig());  
  9.     if  (!executed) ...{  
  10.         if  (preResultListeners !=  null ) ...{  
  11.         Iterator iterator = preResultListeners.iterator();  
  12.         while  (iterator.hasNext()) ...{  
  13.             PreResultListener listener  
  14.             = (PreResultListener) iterator.next();  
  15.             listener.beforeResult(this , resultCode);  
  16.         }  
  17.         }  
  18.         if  (proxy.getExecuteResult())  
  19.         executeResult();  
  20.         executed = true ;  
  21.     }  
  22.     return  resultCode;  
  23.     }  
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:
Java代码 复制代码
  1. public   abstract   class  AroundInterceptor  implements  Interceptor  
  2. ...{  
  3.     protected  Log log = LogFactory.getLog( this .getClass());  
  4.       
  5.     public   void  destroy() ...{  
  6.     }  
  7.       
  8.     public   void  init() ...{  
  9.     }  
  10.       
  11.     public  String intercept(ActionInvocation  invocation)  throws  Exception ...{  
  12.     String result = null ;  
  13.     before(invocation);  
  14.     result = invocation.invoke();  
  15.     after(invocation, result);  
  16.     return  result;  
  17.     }  
  18.       
  19.     protected   abstract   void  after  
  20.     (ActionInvocation  actioninvocation , String string) throws  Exception;  
  21.       
  22.     protected   abstract   void  before(ActionInvocation  actioninvocation )  
  23.     throws  Exception;  
  24. }  
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:
Java代码 复制代码
  1. public   class  ParametersInterceptor  extends  AroundInterceptor ...{  
  2. protected   void  after(ActionInvocation  dispatcher, String result)  
  3. throws  Exception ...{  
  4. }  
  5. protected   void  before(ActionInvocation  invocation)  throws  Exception  
  6. ...{  
  7. if  (!(invocation.getAction()  instanceof  NoParameters)) ...{  
  8. final  Map parameters =  
  9. ActionContext.getContext().getParameters(); ⑴  
  10. if  (log.isDebugEnabled()) ...{  
  11. log.debug("Setting params "  + parameters);  
  12. }  
  13. ActionContext invocationContext =  
  14. invocation.getInvocationContext();  
  15. try  ...{  
  16. invocationContext.put(  
  17. InstantiatingNullHandler.CREATE_NULL_OBJECTS,  
  18. Boolean.TRUE);  
  19. invocationContext.put(  
  20. XWorkMethodAccessor.DENY_METHOD_EXECUTION,  
  21. Boolean.TRUE);  
  22. invocationContext.put(  
  23. XWorkConverter.REPORT_CONVERSION_ERRORS,  
  24. Boolean.TRUE);  
  25. if  (parameters !=  null ) ...{  
  26. final  OgnlValueStack stack =  
  27. ActionContext.getContext().getValueStack(); ⑵  
  28. for  (Iterator iterator =parameters.entrySet().iterator();  
  29. iterator.hasNext();  
  30. ) ...{  
  31. Map.Entry entry = (Map.Entry) iterator.next();  
  32. stack.setValue( ⑷  
  33. entry.getKey().toString(),  
  34. entry.getValue());  
  35. }  
  36. }  
  37. finally  ...{  
  38. invocationContext.put(  
  39. InstantiatingNullHandler.CREATE_NULL_OBJECTS,  
  40. Boolean.FALSE);  
  41. invocationContext.put(  
  42. XWorkMethodAccessor.DENY_METHOD_EXECUTION,  
  43. Boolean.FALSE);  
  44. invocationContext.put(  
  45. XWorkConverter.REPORT_CONVERSION_ERRORS,  
  46. Boolean.FALSE);  
  47. }  
  48. }  
  49. }  
  50. }  
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。
分享到:
评论
2 楼 wtuddd001 2008-10-06  
                 
1 楼 wtuddd001 2008-10-06  
 

相关推荐

    struts2.0中文教程

    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)

    Struts 2.0系列(MAX),pdf格式,全...Struts 2的基石——拦截器(Interceptor) 在Struts 2中实现IoC 在Struts 2中实现文件上传 在Struts 2中实现CRUD Struts 2中的OGNL Strus 2的新表单标志的使用 Struts 2与AJAX

    Struts2.0中文教程权威版

    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中用...

    个人认为目前最完备的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

    struts2.0.jar

    · 引入拦截器: Struts 2为拦截器(interceptor)提供了全面支持。拦截器可在Action类执行前后加以执行。拦截器经配置后,可以把工作流程或者验证等常见功能作用到请求上。所有请求通过一组拦截器传送,之后再发送到...

    struts2入门教程

    很好的struts2入门教程... ·拦截器(Interceptor) ·Struts 2中实现IoC ·Struts 2中实现文件上传 ·Struts 2中的OGNL ·Strus 2的新表单标签的使用 ·Struts 2与AJAX ·Struts2分页 ·完全Struts's Tiles入门

    spring2.5 struts2.0 hibernate3.2.5 搭建的企业级开发基础模块

    还有登录拦截器:com.light.framework.interceptor 字符集过滤器:com.light.framework.filter 项目字符集请用UTF-8 com.light.framework包中还有些小东西 自己看看吧 我是用MyEclipse6.0开发的(MyEclipse...

    jfreechar 整合struts2.1.8版本生成线图,饼图,柱形图

    如果Action中引用了其它的拦截器 默认的拦截器将无效 --> <default-interceptor-ref name="mystack"></default-interceptor-ref> <!-- 全局results配置 --> <result name="input">/error.jsp ...

    J2EE应用开发详解

    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 ...

Global site tag (gtag.js) - Google Analytics