基于Struts2 Result Type为chain 的Action之间数据传递_struts2中的action

其他范文 时间:2020-02-28 02:21:47 收藏本文下载本文
【www.daodoc.com - 其他范文】

基于Struts2 Result Type为chain 的Action之间数据传递由刀豆文库小编整理,希望给你工作、学习、生活带来方便,猜你可能喜欢“struts2中的action”。

chain:基本用途是构造成一条动作链。前一个Action将控制权转交给后一个Action,而前一个Action的状态在后一个Action里仍然保持着。

我现在有一个场景,FirstAction 通过chain的方式,将控制权交给 SecondAction。FirstAction对应的页面代码为first.ftl,SecondAction对应的页面代码为second.ftl。假设我们的FirstAction如下定义:

public cla SecondAction extends ActionSupport{ private CustomUser user = null;

public String execute()throws Exception { // 利用user做事情或显示在页面上 }

// getter setter }

意思很明确了,通过first.ftl的输入,到DB中或其他,生成了我们的CustomUser对象,这个CustomUser对象将要在SecondAction使用。

于是我们想到了要配置FirstAction 的 name为toSecond的 Result type为 chain,将 生成的CustomUser对象传递到 SecondAction中,我们也这样做了,但是 经过调试,发现在SecondAction中没有得到 FirstAction中的CustomUser对象。

SecondAction是这样实现的:

public cla SecondAction extends ActionSupport{ private CustomUser user = null;

public String execute()throws Exception { // 利用user做事情或显示在页面上 }

// getter setter }

看一下ChainingInterceptor.java的实现,发现有这样的注释:

An interceptor that copies all the properties of every object in the value stack to the currently executing object

.在 FirstAction 中CustomUser user 并没有在 value stack 中,所以没有拷贝到SecondAction中。

知道了问题所在,就要解决。首先是想换一种方式去做,将我们要传递的参数通过 其他 Result type 如redirectAction去传递。例如:

SecondAction

execute

${user}

但这样做的缺点是,1.我们要在浏览器上看到很长很乱的URL(如果超过URL长度限制那就更悲剧了)。2.暴露这些参数总感觉很不爽。

3.自定义的对象不能用这种方式传递,要么传String、或JsonObject等。

另外一个解决办法:

因为Result type为chain时,在执行SecondAction时,它的上一个Action,也就是FirstAction的实例并没有被销毁,FirstAction的实例被加入到了ValueStack中。所以,实现的思路就是,增加一个拦截器,在执行Actioin前判断一下,当前Action是否需要从前面的Action实例中获取数据。

这个可以通过注解的方式告诉拦截器,当前的action需要什么样的对象。思路明确了,来看看代码: 注解类:ChainTransParam.java import java.lang.annotation.Documented;import java.lang.annotation.ElementType;import java.lang.annotation.Retention;import java.lang.annotation.RetentionPolicy;import java.lang.annotation.Target;

@Target(ElementType.FIELD)@Retention(RetentionPolicy.RUNTIME)@Documented public @interface ChainTransParam { String fieldName()default “”;}

拦截器实现:ChainParameterInterceptor.java /** * Result type 为chain时 可通过注解的方式实现参数传递 此参数为前置Action的成员变量、并提供getter方法

* 此参数并不要求一定要在值栈中 * * @author liming */

public cla ChainParameterInterceptor extends AbstractInterceptor {

private static final long serialVersionUID =-***6358L;

@Override public String intercept(ActionInvocation invocation)throws Exception { ValueStack stack = invocation.getStack();CompoundRoot root = stack.getRoot();

// 值栈不为null 且已经有前置Action // 栈最顶层(index = 0)为当前Action、紧接着(index = 1)为前置Action if(root == null || root.size()

// 当前Action对象

Object target = invocation.getAction();

Field[] fields = target.getCla().getDeclaredFields();

// 遍历此Action对象的属性 是否有RecieveData注解

for(Field field : fields){ if(field.isAnnotationPresent(ChainTransParam.cla)){ ChainTransParam rData = field.getAnnotation(ChainTransParam.cla);// 取得源数据字段名

String fromName = rData.fieldName();fromName = StringUtils.isEmpty(fromName)? field.getName(): fromName;

// 取得最近的前置Action Object srcAction = root.get(1);

// 取得对应字段的值

Object value = ReflectionUtils.getFieldValue(srcAction, srcAction.getCla(), field.getName());// 设定值

ReflectionUtils.setFieldValue(target, field.getName(), field.getType(), value);} }

return invocation.invoke();}

@SuppreWarnings(“unused”)private Object findFieldValue(CompoundRoot root, Field field){ Object value = null;

int size = root.size();

// 按顺序遍历前置Action for(int index = 1;index

Object tmp = ReflectionUtils.getFieldValue(srcAction, srcAction.getCla(), field.getName());// 取得对应字段的值 则返回

// 问题:如果前置Action中该字段本身就为null 则无法处理 if(tmp!= null){ break;} }

return value;} }

在拦截器的实现中,我是只取得前一个Action中的数据,并没有迭代寻找整个ValueStack的Action,也是可以这样实现的,请看我的findFieldValue方法的实现,但这个方法在此拦截器中并没有使用上。因为我不想这样做。代码完毕之后,配置好拦截器,我们只要在 SecondAction中 这样定义即可:

public cla SecondAction extends ActionSupport{ @ChainTransParam private CustomUser user = null;

public String execute()throws Exception { // 利用user做事情或显示在页面上 }

// getter setter }

当在执行SecondAction之前,拦截器会去查找FirstAction,是否有 user 对象,有则将值拷贝到 SecondAction 中。

ChainTransParam 注解 允许输入参数名,没有输入则默认根据变量名去查找。

注:Struts2 Reference里的意思是不提倡使用Result Type Chain。

另:ReflectionUtils.java 实现: import java.lang.reflect.Field;import java.lang.reflect.InvocationTargetException;import java.lang.reflect.Method;

import org.apache.commons.lang.StringUtils;import org.apache.commons.logging.Log;import org.apache.commons.logging.LogFactory;

public abstract cla ReflectionUtils { private static final Log logger = LogFactory.getLog(ReflectionUtils.cla);

public static void setFieldValue(Object target, String fname, Cla ftype, Object fvalue){ setFieldValue(target, target.getCla(), fname, ftype, fvalue);}

public static void setFieldValue(Object target, Cla clazz, String fname, Cla ftype, Object fvalue){ if(target == null || fname == null || “”.equals(fname)||(fvalue!= null &&!ftype.isAignableFrom(fvalue.getCla()))){ return;}

try { Method method = clazz.getDeclaredMethod(“set” + Character.toUpperCase(fname.charAt(0))+ fname.substring(1), ftype);//if(!Modifier.isPublic(method.getModifiers())){ method.setAcceible(true);//} method.invoke(target, fvalue);} catch(Exception me){ if(logger.isDebugEnabled()){ logger.debug(me);}

try { Field field = clazz.getDeclaredField(fname);//if(!Modifier.isPublic(field.getModifiers())){ field.setAcceible(true);//} field.set(target, fvalue);} catch(Exception fe){ if(logger.isDebugEnabled()){ logger.debug(fe);} } } }

public static Object getFieldValue(Object target, String fname){ return getFieldValue(target, target.getCla(), fname);}

public static Object getFieldValue(Object target, Cla clazz, String fname){ if(target == null || fname == null || “”.equals(fname)){ return null;}

boolean exCatched = false;try { String methodname = “get” + StringUtils.capitalize(fname);Method method = clazz.getDeclaredMethod(methodname);//if(!Modifier.isPublic(method.getModifiers())){ method.setAcceible(true);//} return method.invoke(target);} catch(NoSuchMethodException e){ exCatched = true;} catch(InvocationTargetException e){ exCatched = true;} catch(IllegalAcceException e){ exCatched = true;}

if(exCatched){ try { Field field = clazz.getDeclaredField(fname);//if(!Modifier.isPublic(field.getModifiers())){ field.setAcceible(true);//} return field.get(target);} catch(Exception fe){ if(logger.isDebugEnabled()){ logger.debug(fe);} } } return null;} }

下载基于Struts2 Result Type为chain 的Action之间数据传递word格式文档
下载基于Struts2 Result Type为chain 的Action之间数据传递.doc
将本文档下载到自己电脑,方便修改和收藏。
点此处下载文档

文档为doc格式

    热门文章
      整站推荐
        点击下载本文