- PrepareInterceptor拦截器的用法:
1、若Action实现了Preparable接口,则Action方法需实现prepare()方法;
2、PrepareInterceptor拦截器Struts将调用prepare()方法;
@Override public Member getModel() { return this.member; } @Override public void prepare() throws Exception { // 如果没有id请求参数,说明为create if (this.id == null) { this.member = new Member(); } // 如果有id请求参数,说明为edit else { this.member = memberDao.get(this.id); } }
3、PrepareInteceptor拦截器根据firstCallPrepareDo属性决定获取prepareActionMethodName、prepareDoActionMethodName的顺序,默认情况下先获取prepareActionMethodName,如果没有该方法,就寻找prepareDoActionMethodName()。如果找到对应的方法就调用该方法,若都不存在,则不执行;
4、PrepareInterceptor拦截器会根据alwaysInvokePrepare属性决定是否执行prepare()方法,默认该属性为true,如果要修改该属性值为false,则需要在struts.xml配置文件中修改,具体重写拦截器属性值的方案参考:http://struts.apache.org/docs/interceptors.html#Interceptors-InterceptorParameterOverriding(默认提供了三种重写拦截器属性值的方法)。
- 使用paramsPrepareParamsStack拦截器栈
1、paramsPrepareParams从字面上理解,这个stack的拦截器调用的顺序为:首先调用params,然后调用prepare,接下来调用modelDriven,然后再调用params;
2、Struts2.0的设计上要求modelDriven在params之前调用,而业务中prepare要负责准备model,准备model又需要参数,这就需要在prepare之前调用params拦截器设置相关参数,这个也就是创建paramsPrepareParamsStack的原因。
3、执行流程如下:
3.1、params拦截器首先给action中的相关参数赋值,如id;
3.2、prepare拦截器执行prepare方法,prepare方法中会根据参数,如id,去调用业务逻辑,设置model对象;
3.3、modelDriven拦截器将model对象压入valuestack,这里的model对象就是在prepare中创建的;
3.4、params拦截器在将参数赋值给model对象;
3.5、action的业务逻辑执行。
为什么使用ModelDriven拦截器?
①在我们struts2的企业级开发中,把Action和Model清晰的隔离开是很有必要的。有些Action不代表任何Model对象,它们的功能仅限于显示服务。把动作对象和model模型隔离开说明我们的模型对象不能再是动作对象的实例,那么我们如何让提交的参数映射到model对象里面去呢?那就要使用modeldriven拦截器。
②实现了modeldriven拦截器的Action类需要实现getModel()方法。当用户触发动作时,ModelDriven会调用相应Action动作对象的getModel()方法,并且把getModel()方法返回的model对象压入到值栈中的Object stack的栈顶。那么Parameter拦截器将会将页面提交的参数映射到栈顶的模型对象相应的属性当中去,如果某个参数模型对象中没有与之匹配的属性,那么将从栈顶的下一个对象中继续找与之匹配的属性并且映射到相应的属性中去。
那么为什么需要使用Preparable拦截器呢?
①struts2的ModelDriven的getModel()方法返回一个model对象,ModelDriven将该对象压入到栈顶中去,而这里的Preparable拦截器则负责为我们的getModel()方法准备model对象。
②实现了Preparable接口的Action类需要实现prepare()方法。但是在执行prepare()方法之前,struts尝试执行prepare[ActionMethodName]()方法,若prepare[ActionMethodName]()方法不存在,那么尝试执行下一个prepareDo[ActionMethodName]方法,如果也不存在就都不执行。最后再执行prepare()方法。这里需要说明的是,加入我们的Action中有一个处理action请求的add()方法,在Action类中添加prepareAdd()或者prepareDoAdd()方法,那么就可以通过该方法来为当前的Action准备模型对象并压入到栈顶,是的传过来的参数成功映射到model对象中去。
③我们可以通过设置PrepareInterceptor拦截器的alwaysInvokePrepare属性来告诉struts是否执行prepare()方法。默认是执行prepare()方法的。如果想要设置不执行prepare()方法,方法如下:
在struts.xml配置文件中配置
<interceptors>
<interceptor-stack name="parentStack">
<interceptor-ref name="拦截器栈名">
<param name="prepare.alwaysInvokePrepare">false</param>
</interceptor-ref>
</interceptor-stack>
</interceptors>
paramsPrepareParamsStack栈有什么作用呢?
①paramsPrepareParamsStack是用来设置action请求时执行拦截器的循序。从字面上理解来说,这个stack的拦截器调用拦截器的顺序是为如下:
<interceptor-stack name="paramsPrepareParamsStack"><interceptor-ref name="exception"/>
<interceptor-ref name="alias"/>
<interceptor-ref name="i18n"/>
<interceptor-ref name="checkbox"/>
<interceptor-ref name="datetime"/>
<interceptor-ref name="multiselect"/>
<!--往栈顶对象中填充参数 此时栈顶对象时Action类-->
<interceptor-ref name="params"/>
<interceptor-ref name="servletConfig"/>
<!--准备model对象-->
<interceptor-ref name="prepare"/>
<interceptor-ref name="chain"/>
<!--将model对象压入到object stack的栈顶-->
<interceptor-ref name="modelDriven"/>
<interceptor-ref name="fileUpload"/>
<interceptor-ref name="staticParams"/>
<interceptor-ref name="actionMappingParams"/>
<!--往栈顶对象填充参数 此时栈顶对象是model对象-->
<interceptor-ref name="params"/>
<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>
②struts2设计时将modeldriven拦截器放到了params拦截器之前。这里参数就能成功的设置到栈顶的model对象当中去,但是在prepare拦截器准备model对象时有需要某些提交过来的参数,那么就需要在执行modeldriven之前再执行一次params拦截器,这就是设置拦截器栈paramsPrepareParamsStack的原因。
根据paramsPrepareParamsStack的拦截器顺序,我们可以看出其重要的几个流程如下:
1)当发出action请求时,struts2创建一个对应的Action类放到栈顶,第一个params拦截器将特定的属性映射到Action对象中去。
2)prepare拦截器根据Action中的某些属性来准备model对象。
3)modelDriven拦截器将准备好的model对象压入到值栈的栈顶。
4)params拦截器再将参数映射到栈顶的model对象中去。
5)执行Action类中的action请求对象的方法。