Struts2的运行流程以及关键拦截器介绍

Struts2的运行流程

1、ActionProxyAction的一个代理类,也就是说Action的调用是通过ActionProxy实现的,其实就是调用了ActionProxy.execute()方法,而该方法又调用了ActionInvocation.invoke()方法,上图中的StrutsActionProxy类实现类ActionProxy代理类。

2、ActionInvocation就是Action的调用者。ActionInvocationAction的执行过程中,负责Interceptor、ActionResult等一系列元素的调度。

Params拦截器

<interceptor-stack name="defaultStack">
                <interceptor-ref name="exception"/>
                <interceptor-ref name="alias"/>
                <interceptor-ref name="servletConfig"/>
                <interceptor-ref name="i18n"/>
                <interceptor-ref name="prepare"/>
                <interceptor-ref name="chain"/>
                <interceptor-ref name="scopedModelDriven"/>
                <interceptor-ref name="modelDriven"/>
                <interceptor-ref name="fileUpload"/>
                <interceptor-ref name="checkbox"/>
                <interceptor-ref name="multiselect"/>
                <interceptor-ref name="staticParams"/>
                <interceptor-ref name="actionMappingParams"/>
                <interceptor-ref name="params">
                    <param name="excludeParams">^action:.*,^method:.*</param>
                </interceptor-ref>
                <interceptor-ref name="conversionError"/>
                <interceptor-ref name="validation">
                    <param name="excludeMethods">input,back,cancel,browse</param>
                </interceptor-ref>
                <interceptor-ref name="workflow">
                    <param name="excludeMethods">input,back,cancel,browse</param>
                </interceptor-ref>
                <interceptor-ref name="debugging"/>
                <interceptor-ref name="deprecation"/>
            </interceptor-stack>

Params拦截器是struts2默认的拦截器之一,其作用如下:

Parameters 拦截器将把表单字段映射到ValueStack栈的栈顶对象的各个属性中.如果某个字段在模型里没有匹配的属性,Param拦截器将尝试ValueStack栈中的下一个对象

ModelDriven拦截器

ModelDrivenInterceptor 的interceptor()  方法:

public String intercept(ActionInvocation invocation)
     throws Exception
   {
   //获取action对象
   Object action = invocation.getAction();
    //检查是否实现了ModelDriven接口
    if ((action instanceof ModelDriven)) {
      ModelDriven modelDriven = (ModelDriven)action;
      //取值栈
      ValueStack stack = invocation.getStack();
      //获取Action中的成员变量对象
      Object model = modelDriven.getModel();
      if (model != null) {
      //压入值栈栈顶 
      stack.push(model);
     }
     if (refreshModelBeforeResult) {
        invocation.addPreResultListener(new RefreshModelBeforeResult(modelDriven, model));
     }
    }
    //执行下一个拦截器操作
    return invocation.invoke();
 }

1、在使用Struts作为前端的企业级应用程序时ActionModel 清晰地隔离开是有必要的:有些Action 不代表任何Model对象,它们的功能仅限于提供视图服务
2、当用户触发 add 请求时,ModelDriven拦截器将调用EmployeeAction对象的getModel()方法, 并把返回的模型(Employee实例)压入到ValueStack.
3、接下来Parameters拦截器将把表单字段映射到ValueStack栈的栈顶对象的各个属性中.因为此时ValueStack栈的栈顶元素是刚被压入的模型(Employee)对象,所以该模型将被填充.如果某个字段在模型里没有匹配的属性,Param拦截器将尝试ValueStack栈中的下一个对象
总结:通过上述的2个拦截器,可以看出为什么Action实现ModelDriven接口之后,在Action中可以直接使用成员对象变量来接受前台提交来的属性值。

Prepare拦截器

1、Struts 2.0 中的 modelDriven拦截器负责把 Action 类以外的一个对象压入到值栈栈顶
2、prepare拦截器负责准备为getModel() 方法准备 model

PrepareInterceptor拦截器用法

1、Action 实现 Preparable接口,则 Action 方法需实现 prepare() 方法
2、PrepareInterceptor
拦截器将调用 prepare() 方法,prepareActionMethodName()方法【比如 prepareSave()------action中有一个方法名为save】 或 prepareDoActionMethodName ()方法 ]
3、PrepareInterceptor拦截器根据 firstCallPrepareDo 属性决定获取prepareActionMethodNameprepareDoActionMethodName的顺序。默认情况下先获取 prepareActionMethodName (), 如果没有该方法,就寻找prepareDoActionMethodName()。如果找到对应的方法就调用该方法
4、PrepareInterceptor拦截器会根据 alwaysInvokePrepare属性决定是否执行prepare()方法

paramsPrepareParamsStack拦截器栈

1、paramsPrepareParamsStack从字面上理解来说, 这个stack的拦截器调用的顺序为:首先 params然后 prepare,接下来 modelDriven最后再 params
2、Struts 2.0的设计上要求 modelDriven params之前调用,而业务中prepare要负责准备model,准备model又需要参数,这就需要在 prepare之前运行params拦截器设置相关参数,这个也就是创建paramsPrepareParamsStack的原因。
3、流程如下:

1.params拦截器首先给action中的相关参数赋值,如id
2.prepare拦截器执行prepare方法,prepare方法中会根据参数,如id,去调用业务逻辑,设置model对象
3.modelDriven拦截器将model对象压入value stack,这里的model对象就是在prepare中创建的
4.params拦截器再将参数赋值给model对象
5.action的业务逻辑执行

 <interceptor-stack name="paramsPrepareParamsStack">
                <interceptor-ref name="exception"/>
                <interceptor-ref name="alias"/>
                <interceptor-ref name="i18n"/>
                <interceptor-ref name="checkbox"/>
                <interceptor-ref name="multiselect"/>
                <interceptor-ref name="params">
                    <param name="excludeParams">^action:.*,^method:.*</param>
                </interceptor-ref>
                <interceptor-ref name="servletConfig"/>
                <interceptor-ref name="prepare"/>
                <interceptor-ref name="chain"/>
                <interceptor-ref name="modelDriven"/>
                <interceptor-ref name="fileUpload"/>
                <interceptor-ref name="staticParams"/>
                <interceptor-ref name="actionMappingParams"/>
                <interceptor-ref name="params">
                    <param name="excludeParams">^action:.*,^method:.*</param>
                </interceptor-ref>
                <interceptor-ref name="conversionError"/>
                <interceptor-ref name="validation">
                    <param name="excludeMethods">input,back,cancel,browse</param>
                </interceptor-ref>
                <interceptor-ref name="workflow">
                    <param name="excludeMethods">input,back,cancel,browse</param>
                </interceptor-ref>
            </interceptor-stack>


原文地址:https://www.cnblogs.com/elgin-seth/p/5293742.html