Struts2学习总结(十):paramsPrepareParams拦截器栈
2017-07-20 11:48
393 查看
1. paramsPrepareParamsStack:
和defaultStack都是拦截器栈,struts-default默认使用defaultSack
可以在struts.xml文件通过以下方式修改默认的拦截器栈:
2.拦截器栈中的使用顺序:
params->prepare->model-driven->params
Struts2.0的设计上要求modelDriven在params之前调用,而业务中prepare要负责准备model,准备model又需要参数,这就需要在prepare之前调用params拦截器设置相关参数,这个也就是创建paramsPrepareParamsStack的原因。
流程:
params拦截器首先给action的相关参数赋值
prepare拦截器执行prepare方法,prepare方法会根据参数,如id,去调用业务逻辑,设置model对象
model-diven拦截器将model对象压入值栈,这里的model对象就是在prepare中创建
params拦截器将参数值赋给model对象
action的逻辑执行
3.PrepareInterceptor拦截器(prepare)
该拦截器的功能主要是在Action的execute方法之前执行一些业务逻辑。要使拦截器拦截有效,Action要实现Prepareable接口。
源码解释如下:
(2)根据bool值得到一个数组确认了前缀数组[“prepare”,"parepareDo"]的一个字符串数组(这两个字符串已经在源代码确定,不可修改)
(3)然后执行前缀方法(该方法可能为空),进入方法后:
(4.1)获取当前的Action,和当前的Action方法
(4.2判断当前的methodName是否为空
(4.3)然后获取一个前缀方法:getPrefixedMethod:
让目标方法首字母变成了大写
遍历前缀数组,把前缀拼接到目标方法前
尝试从Action中获取拼接好的方法,如果有就返回,没有生成一个NoSuchMethodException的异常
(5)返回到getPrefixedMethod()方法,返回后判断拼接好的方法是否为空,然后接着执行method.invoke方法
(6)回到doIntercept()方法,有一个alwaysInvokePrepare为false,就不会执行实现了Prepareable的Action的prepare()方法
Action实现Prepareable接口,该接口有一个要实现的方法prepare()方法
让需要执行的逻辑放在prepare()方法中,或者如果自己定义的方法叫做xxx,可以加上prepareXxx()方法或prePareDoXxx()方法
上面出现了三个方法prepare(),prepareXxx(),prepareDoXxx()。拦截器执行的顺序为:PrepareInterceptor 拦截器根据 firstCallPrepareDo 属性决定获取 prepareActionMethodName 、prepareDoActionMethodName的顺序。先寻找prepareXxx()方法,如果没有该方法,就寻找prepareDoXxx()方法,最后执行prepare()方法。如果prepareXxx(),prepareDoXxx()同时存在,只会执行prepareXxx()方法。prepare()最后执行,并且是一定会执行。
prepare()方法用于你定义的所有方法之间进行预处理,而prepareXxx()与prepareDoXxx()方法只能用于xxx方法之前的预处理
可以在struts.xml文件里配置,不再调用 prepare方法
4000
<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"/> <interceptor-ref name="params"/> <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"/> <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>
和defaultStack都是拦截器栈,struts-default默认使用defaultSack
可以在struts.xml文件通过以下方式修改默认的拦截器栈:
<default-interceptor-ref name="paramsPrepareParamsStack"></default-interceptor-ref>
2.拦截器栈中的使用顺序:
params->prepare->model-driven->params
Struts2.0的设计上要求modelDriven在params之前调用,而业务中prepare要负责准备model,准备model又需要参数,这就需要在prepare之前调用params拦截器设置相关参数,这个也就是创建paramsPrepareParamsStack的原因。
流程:
params拦截器首先给action的相关参数赋值
prepare拦截器执行prepare方法,prepare方法会根据参数,如id,去调用业务逻辑,设置model对象
model-diven拦截器将model对象压入值栈,这里的model对象就是在prepare中创建
params拦截器将参数值赋给model对象
action的逻辑执行
3.PrepareInterceptor拦截器(prepare)
该拦截器的功能主要是在Action的execute方法之前执行一些业务逻辑。要使拦截器拦截有效,Action要实现Prepareable接口。
源码解释如下:
public String doIntercept(ActionInvocation invocation) throws Exception { //获取 Action 实例 Object action = invocation.getAction(); //判断 Action 是否实现了 Preparable 接口 if (action instanceof Preparable) { try { String[] prefixes; //根据当前拦截器的 firstCallPrepareDo(默认为 false) 属性确定 prefixes if (firstCallPrepareDo) { prefixes = new String[] {ALT_PREPARE_PREFIX, PREPARE_PREFIX}; } else { prefixes = new String[] {PREPARE_PREFIX, ALT_PREPARE_PREFIX}; } //若为 false, 则 prefixes: prepare, prepareDo //调用前缀方法. PrefixMethodInvocationUtil.invokePrefixMethod(invocation, prefixes); } catch (InvocationTargetException e) { Throwable cause = e.getCause(); if (cause instanceof Exception) { throw (Exception) cause; } else if(cause instanceof Error) { throw (Error) cause; } else { throw e; } } //根据当前拦截器的 alwaysInvokePrepare(默认是 true) 决定是否调用 Action 的 prepare 方法 if (alwaysInvokePrepare) { ((Preparable) action).prepare(); } } return invocation.invoke(); }(1)首先获取当前Action实例,然后判断Action是否实现了Prepareable接口
(2)根据bool值得到一个数组确认了前缀数组[“prepare”,"parepareDo"]的一个字符串数组(这两个字符串已经在源代码确定,不可修改)
(3)然后执行前缀方法(该方法可能为空),进入方法后:
PrefixMethodInvocationUtil.invokePrefixMethod(invocation, prefixes) 方法: public static void invokePrefixMethod(ActionInvocation actionInvocation, String[] prefixes) throws InvocationTargetException, IllegalAccessException { //获取 Action 实例 Object action = actionInvocation.getAction(); //获取要调用的 Action 方法的名字(update) String methodName = actionInvocation.getProxy().getMethod(); if (methodName == null) { // if null returns (possible according to the docs), use the default execute methodName = DEFAULT_INVOCATION_METHODNAME; } //获取前缀方法 Method method = getPrefixedMethod(prefixes, methodName, action); //若方法不为 null, 则通过反射调用前缀方法 if (method != null) { method.invoke(action, new Object[0]); } }(4)进入方法后:
(4.1)获取当前的Action,和当前的Action方法
(4.2判断当前的methodName是否为空
(4.3)然后获取一个前缀方法:getPrefixedMethod:
让目标方法首字母变成了大写
遍历前缀数组,把前缀拼接到目标方法前
尝试从Action中获取拼接好的方法,如果有就返回,没有生成一个NoSuchMethodException的异常
(5)返回到getPrefixedMethod()方法,返回后判断拼接好的方法是否为空,然后接着执行method.invoke方法
(6)回到doIntercept()方法,有一个alwaysInvokePrepare为false,就不会执行实现了Prepareable的Action的prepare()方法
PrefixMethodInvocationUtil.getPrefixedMethod 方法: public static Method getPrefixedMethod(String[] prefixes, String methodName, Object action) { assert(prefixes != null); //把方法的首字母变为大写 String capitalizedMethodName = capitalizeMethodName(methodName); //遍历前缀数组 for (String prefixe : prefixes) { //通过拼接的方式, 得到前缀方法名: 第一次 prepareUpdate, 第二次 prepareDoUpdate String prefixedMethodName = prefixe + capitalizedMethodName; try { //利用反射获从 action 中获取对应的方法, 若有直接返回. 并结束循环. return action.getClass().getMethod(prefixedMethodName, EMPTY_CLASS_ARRAY); } catch (NoSuchMethodException e) { // hmm -- OK, try next prefix if (LOG.isDebugEnabled()) { LOG.debug("cannot find method [#0] in action [#1]", prefixedMethodName, action.toString()); } } } return null; }实现此拦截器的步骤:
Action实现Prepareable接口,该接口有一个要实现的方法prepare()方法
让需要执行的逻辑放在prepare()方法中,或者如果自己定义的方法叫做xxx,可以加上prepareXxx()方法或prePareDoXxx()方法
上面出现了三个方法prepare(),prepareXxx(),prepareDoXxx()。拦截器执行的顺序为:PrepareInterceptor 拦截器根据 firstCallPrepareDo 属性决定获取 prepareActionMethodName 、prepareDoActionMethodName的顺序。先寻找prepareXxx()方法,如果没有该方法,就寻找prepareDoXxx()方法,最后执行prepare()方法。如果prepareXxx(),prepareDoXxx()同时存在,只会执行prepareXxx()方法。prepare()最后执行,并且是一定会执行。
prepare()方法用于你定义的所有方法之间进行预处理,而prepareXxx()与prepareDoXxx()方法只能用于xxx方法之前的预处理
可以在struts.xml文件里配置,不再调用 prepare方法
代码示例: <interceptors> <interceptor-stack name="mycustomStack"> <interceptor-ref name="paramsPrepareParamsStack"> <param name="prepare.alwaysInvokePrepare">false</param> </interceptor-ref> </interceptor-stack> </interceptors>
4000
相关文章推荐
- Spring整合Struts2 wel.xml中写spring核心配置文件路径问题,顺便总结下我学习SSH整合的过程
- Struts2基础学习总结
- 学习struts2建bbs总结一:用powerdesigner建数据库并自动生成测试数据
- Struts2学习总结(三):Action与ActionSupport
- Struts2学习总结
- 学习struts2总结
- Struts2系统学习(6)action中方法调用的三种方式总结
- Struts学习总结(八)---使用Struts2实现用户信息的CRUD操作(二:添加操作)
- Struts学习总结(九)---使用Struts2实现用户信息的CRUD操作(三:修改操作)
- struts2 学习总结(11)
- 学习struts2建bbs总结六:hibernate分页查询的问题--分页后程序定时无响应
- struts2学习总结
- Struts2拦截器总结学习
- [Struts2]Struts2学习总结
- Struts2 学习总结
- struts2学习 EL表达式总结
- [原创]java WEB学习笔记75:Struts2 学习之路-- 总结 和 目录
- 【转载】struts2 学习总结 ---- Ajax
- [原创]java WEB学习笔记66:Struts2 学习之路--Struts的CRUD操作( 查看 / 删除/ 添加) 使用 paramsPrepareParamsStack 重构代码 ,PrepareInterceptor拦截器,paramsPrepareParamsStack 拦截器栈
- struts2 学习总结 ---- Ajax