admin 管理员组

文章数量: 1184232


2024年2月23日发(作者:java中switch语句的用法举例)

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

我现在有一个场景,FirstAction 通过chain的方式,将控制权交给 SecondAction。FirstAction对应的页面代码为,SecondAction对应的页面代码为。

假设我们的FirstAction如下定义:

public class SecondAction extends ActionSupport{

private CustomUser user = null;

public String execute() throws Exception {

// 利用user做事情或显示在页面上

}

// getter setter

}

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

于是我们想到了要配置FirstAction 的 name为toSecond的 Result type为 chain,将 生成的CustomUser对象传递到 SecondAction中,

我们也这样做了,但是 经过调试,发现在SecondAction中没有得到 FirstAction中的CustomUser对象。

SecondAction是这样实现的:

public class SecondAction extends ActionSupport{

private CustomUser user = null;

public String execute() throws Exception {

// 利用user做事情或显示在页面上

}

// getter setter

}

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

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需要什么样的对象。

思路明确了,来看看代码:

注解类:

import nted;

import tType;

import ion;

import ionPolicy;

import ;

@Target()

@Retention(E)

@Documented

public @interface ChainTransParam {

String fieldName() default "";

}

拦截器实现:

/**

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

* 此参数并不要求一定要在值栈中

*

* @author liming

*/

public class ChainParameterInterceptor extends AbstractInterceptor {

private static final long serialVersionUID = -82793358L;

@Override

public String intercept(ActionInvocation invocation) throws Exception {

ValueStack stack = ck();

CompoundRoot root = t();

// 值栈不为null 且已经有前置Action

// 栈最顶层(index = 0)为当前Action、紧接着(index = 1) 为前置Action

if (root == null || () <= 2) {

return ();

}

// 当前Action对象

Object target = ion();

Field[] fields = ss().getDeclaredFields();

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

for (Field field : fields) {

if (tationPresent()) {

ChainTransParam rData = otation();

// 取得源数据字段名

String fromName = ame();

fromName = y(fromName) ? e() : fromName;

// 取得最近的前置Action

Object srcAction = (1);

// 取得对应字段的值

Object value = ldValue(srcAction, ss(), e());

// 设定值

ldValue(target, e(), e(), value);

}

}

return ();

}

@SuppressWarnings("unused")

private Object findFieldValue(CompoundRoot root, Field field) {

Object value = null;

int size = ();

// 按顺序遍历前置Action

for (int index = 1; index < size; index++) {

Object srcAction = (index);

Object tmp = ldValue(srcAction, ss

(), e());

// 取得对应字段的值 则返回

// 问题:如果前置Action中该字段本身就为null 则无法处理

if (tmp != null) {

break;

}

}

return value;

}

}

在拦截器的实现中,我是只取得前一个Action中的数据,并没有迭代寻找整个ValueStack的Action,也是可以这样实现的,请看我的findFieldValue方法的实现,但这个方法在此拦截器中并没有使用上。因为我不想这样做。

代码完毕之后,配置好拦截器,

我们只要在 SecondAction中 这样定义即可:

public class 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。

另: 实现:

import ;

import tionTargetException;

import ;

import Utils;

import ;

import tory;

public abstract class ReflectionUtils {

private static final Log logger = ();

public static void setFieldValue(Object target, String fname, Class ftype, Object fvalue) {

setFieldValue(target, ss(), fname, ftype, fvalue);

}

public static void setFieldValue(Object target, Class clazz, String fname, Class ftype, Object fvalue) {

if (target == null || fname == null || "".equals(fname)

|| (fvalue != null && !gnableFrom(ss()))) {

return;

}

try {

Method method = laredMethod(

"set" + rCase((0)) + ing(1), ftype);

//if (!ic(ifiers())) {

essible(true);

//}

(target, fvalue);

}

catch (Exception me) {

if (gEnabled()) {

(me);

}

try {

Field field = laredField(fname);

//if (!ic(ifiers())) {

essible(true);

//}

(target, fvalue);

}

catch (Exception fe) {

if (gEnabled()) {

(fe);

}

}

}

}

public static Object getFieldValue(Object target, String fname) {

return getFieldValue(target, ss(), fname);

}

public static Object getFieldValue(Object target, Class clazz, String fname) {

if (target == null || fname == null || "".equals(fname)) {

return null;

}

boolean exCatched = false;

try {

String methodname = "get" + lize(fname);

Method method = laredMethod(methodname);

//if (!ic(ifiers())) {

essible(true);

//}

return (target);

}

catch (NoSuchMethodException e) {

exCatched = true;

}

catch (InvocationTargetException e) {

exCatched = true;

}

catch (IllegalAccessException e) {

exCatched = true;

}

if (exCatched) {

try {

Field field = laredField(fname);

//if (!ic(ifiers())) {

essible(true);

//}

return (target);

}

catch (Exception fe) {

if (gEnabled()) {

(fe);

}

}

}

return null;

}

}


本文标签: 没有 拦截器 方式 对象 注解