Struts2学习总结(十):paramsPrepareParams拦截器栈
来源:互联网 发布:单片机 http请求 编辑:程序博客网 时间:2024/05/22 01:58
1. paramsPrepareParamsStack:
<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的异常
(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()方法只能用于xxx方法之前的预处理
可以在struts.xml文件里配置,不再调用 prepare方法
代码示例:<interceptors> <interceptor-stack name="mycustomStack"> <interceptor-ref name="paramsPrepareParamsStack"> <param name="prepare.alwaysInvokePrepare">false</param> </interceptor-ref> </interceptor-stack></interceptors>
阅读全文
0 0
- Struts2学习总结(十):paramsPrepareParams拦截器栈
- Struts2-9 modelDriven与paramsPrepareParams拦截器
- 16.Struts2_使用ParamsPrepareParams拦截器栈
- Struts2(十)---拦截器
- Struts2学习总结(八):拦截器
- Struts2学习笔记(十)方法拦截器
- Struts2拦截器总结学习
- struts2 18拦截器详解(二十) --- 拦截器总结
- struts2 学习总结 ---- 拦截器(interceptor)
- 【转载】struts2 学习总结 ---- 拦截器(interceptor)
- Struts2拦截器总结
- Struts2 拦截器总结
- Struts2拦截器总结
- struts2拦截器学习
- Struts2拦截器学习
- Struts2拦截器学习
- Struts2拦截器学习
- 学习 -- Struts2拦截器
- 第四章:Django模型——admin后台管理
- 504. Base 7
- 206. Reverse Linked List
- 中企动力与湖南源峰现代农业公司同行 共享全网营销平台
- 北京网信办整治自媒体八大乱象 腾讯网易凤凰在列
- Struts2学习总结(十):paramsPrepareParams拦截器栈
- linux 网卡对应网口查看方式
- echarts 实现柱状图左右横向显示
- 关于QT的那些事(二)
- N-Queens II
- C#设计模式(一)单例模式
- 【python学习笔记】15:numpy创建各种数组
- 启动docker,进入docker
- 第四章:Django模型——添加 Event发布会的表 报错