Struts2的运行流程
1、ActionProxy是Action的一个代理类,也就是说Action的调用是通过ActionProxy实现的,其实就是调用了ActionProxy.execute()方法,而该方法又调用了ActionInvocation.invoke()方法,上图中的StrutsActionProxy类实现类ActionProxy代理类。
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作为前端的企业级应用程序时把Action和
Model 清晰地隔离开是有必要的:有些Action
类不代表任何Model对象,它们的功能仅限于提供视图服务
2、当用户触发 add 请求时,ModelDriven拦截器将调用EmployeeAction对象的getModel()方法, 并把返回的模型(Employee实例)压入到ValueStack栈.
2、当用户触发 add 请求时,ModelDriven拦截器将调用EmployeeAction对象的getModel()方法, 并把返回的模型(Employee实例)压入到ValueStack栈.
3、接下来Parameters拦截器将把表单字段映射到ValueStack栈的栈顶对象的各个属性中.因为此时ValueStack栈的栈顶元素是刚被压入的模型(Employee)对象,所以该模型将被填充.如果某个字段在模型里没有匹配的属性,Param拦截器将尝试ValueStack栈中的下一个对象
总结:通过上述的2个拦截器,可以看出为什么Action实现ModelDriven接口之后,在Action中可以直接使用成员对象变量来接受前台提交来的属性值。
总结:通过上述的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 ()方法 ]
2、PrepareInterceptor拦截器将调用 prepare() 方法,prepareActionMethodName()方法【比如 prepareSave()------action中有一个方法名为save】 或 prepareDoActionMethodName ()方法 ]
3、PrepareInterceptor拦截器根据
firstCallPrepareDo 属性决定获取prepareActionMethodName、prepareDoActionMethodName的顺序。默认情况下先获取
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>