免费视频淫片aa毛片_日韩高清在线亚洲专区vr_日韩大片免费观看视频播放_亚洲欧美国产精品完整版

打開APP
userphoto
未登錄

開通VIP,暢享免費電子書等14項超值服

開通VIP
基于Struts2 Result Type為chain 的Action之間數(shù)據(jù)傳遞
chain:基本用途是構造成一條動作鏈。前一個Action將控制權轉交給后一個Action,而前一個Action的狀態(tài)在后一個Action里仍然保持著。
我現(xiàn)在有一個場景,F(xiàn)irstAction 通過chain的方式,將控制權交給 SecondAction。FirstAction對應的頁面代碼為first.ftl,SecondAction對應的頁面代碼為second.ftl。
假設我們的FirstAction如下定義:
public class FirstAction extends ActionSupport{

    
private String input1 = null;  // 由first.ftl頁面輸入值
    private String input2 = null;  // 由first.ftl頁面輸入值
    private CustomUser user = null;// 并不在first.ftl頁面上有相關元素綁定

    
public String execute() throws Exception {
        
//做一些事情,生成了CustomUser
        setCustomUser(ret);

        
return "toSecond";
    }


    
// getter setter
}


意思很明確了,通過first.ftl的輸入,到DB中或其他,生成了我們的CustomUser對象,這個CustomUser對象將要在SecondAction使用。
于是我們想到了要配置FirstAction 的 name為toSecond的 Result type為 chain,將 生成的CustomUser對象傳遞到 SecondAction中,
我們也這樣做了,但是 經(jīng)過調試,發(fā)現(xiàn)在SecondAction中沒有得到 FirstAction中的CustomUser對象。
SecondAction是這樣實現(xiàn)的:
public class SecondAction extends ActionSupport{
    
private CustomUser user = null;

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


    
// getter setter
}


看一下ChainingInterceptor.java的實現(xiàn),發(fā)現(xiàn)有這樣的注釋:
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中。

知道了問題所在,就要解決。首先是想換一種方式去做,將我們要傳遞的參數(shù)通過 其他 Result type 如redirectAction去傳遞。
例如:

<result type="redirectAction" name="toSecond">
    
<param name="actionName">SecondAction</param>
    
<param name="method">execute</param>
    
<param name="user">${user}</param>
</result>

但這樣做的缺點是,
1.我們要在瀏覽器上看到很長很亂的URL(如果超過URL長度限制那就更悲劇了)。
2.暴露這些參數(shù)總感覺很不爽。
3.自定義的對象不能用這種方式傳遞,要么傳String、或JsonObject等。

另外一個解決辦法:
因為Result type為chain時,在執(zhí)行SecondAction時,它的上一個Action,也就是FirstAction的實例并沒有被銷毀,F(xiàn)irstAction的實例被加入到了ValueStack中。
所以,實現(xiàn)的思路就是,增加一個攔截器,在執(zhí)行Actioin前判斷一下,當前Action是否需要從前面的Action實例中獲取數(shù)據(jù)。

這個可以通過注解的方式告訴攔截器,當前的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 "";
}

攔截器實現(xiàn):ChainParameterInterceptor.java
/**
 * Result type 為chain時 可通過注解的方式實現(xiàn)參數(shù)傳遞 此參數(shù)為前置Action的成員變量、并提供getter方法
 * 此參數(shù)并不要求一定要在值棧中
 * 
 * 
@author liming
 
*/

public class ChainParameterInterceptor extends AbstractInterceptor {

    
private static final long serialVersionUID = -8279316685527646358L;

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

        
// 值棧不為null 且已經(jīng)有前置Action
        
// 棧最頂層(index = 0)為當前Action、緊接著(index = 1) 為前置Action
        if (root == null || root.size() <= 2{
            
return invocation.invoke();
        }


        
// 當前Action對象
        Object target = invocation.getAction();

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

        
// 遍歷此Action對象的屬性 是否有RecieveData注解
        for (Field field : fields) {
            
if (field.isAnnotationPresent(ChainTransParam.class)) {
                ChainTransParam rData 
= field.getAnnotation(ChainTransParam.class);
                
// 取得源數(shù)據(jù)字段名
                String fromName = rData.fieldName();
                fromName 
= StringUtils.isEmpty(fromName) ? field.getName() : fromName;

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

                
// 取得對應字段的值
                Object value = ReflectionUtils.getFieldValue(srcAction, srcAction.getClass(), field.getName());
                
// 設定值
                ReflectionUtils.setFieldValue(target, field.getName(), field.getType(), value);
            }

        }


        
return invocation.invoke();
    }


    @SuppressWarnings(
"unused")
    
private Object findFieldValue(CompoundRoot root, Field field) {
        Object value 
= null;

        
int size = root.size();

        
// 按順序遍歷前置Action
        for (int index = 1; index < size; index++{
            Object srcAction 
= root.get(index);

            Object tmp 
= ReflectionUtils.getFieldValue(srcAction, srcAction.getClass(), field.getName());
            
// 取得對應字段的值 則返回
            
// 問題:如果前置Action中該字段本身就為null 則無法處理
            if (tmp != null{
                
break;
            }

        }


        
return value;
    }

}


在攔截器的實現(xiàn)中,我是只取得前一個Action中的數(shù)據(jù),并沒有迭代尋找整個ValueStack的Action,也是可以這樣實現(xiàn)的,請看我的findFieldValue方法的實現(xiàn),但這個方法在此攔截器中并沒有使用上。因為我不想這樣做。

代碼完畢之后,配置好攔截器,

我們只要在 SecondAction中 這樣定義即可:

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

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


    
// getter setter
}

當在執(zhí)行SecondAction之前,攔截器會去查找FirstAction,是否有 user 對象,有則將值拷貝到 SecondAction 中。
ChainTransParam 注解 允許輸入?yún)?shù)名,沒有輸入則默認根據(jù)變量名去查找。

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


另:ReflectionUtils.java 實現(xiàn):
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 class ReflectionUtils {
    
private static final Log logger = LogFactory.getLog(ReflectionUtils.class);

    
public static void setFieldValue(Object target, String fname, Class<?> ftype, Object fvalue) {
        setFieldValue(target, target.getClass(), 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 && !ftype.isAssignableFrom(fvalue.getClass()))) {
            
return;
        }


        
try {
            Method method 
= clazz.getDeclaredMethod(
                    
"set" + Character.toUpperCase(fname.charAt(0)) + fname.substring(1), ftype);
            
//if (!Modifier.isPublic(method.getModifiers())) {
            method.setAccessible(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.setAccessible(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.getClass(), 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" + StringUtils.capitalize(fname);
            Method method 
= clazz.getDeclaredMethod(methodname);
            
//if (!Modifier.isPublic(method.getModifiers())) {
            method.setAccessible(true);
            
//}
            return method.invoke(target);
        }

        
catch (NoSuchMethodException e) {
            exCatched 
= true;
        }

        
catch (InvocationTargetException e) {
            exCatched 
= true;
        }

        
catch (IllegalAccessException e) {
            exCatched 
= true;
        }


        
if (exCatched) {
            
try {
                Field field 
= clazz.getDeclaredField(fname);
                
//if (!Modifier.isPublic(field.getModifiers())) {
                field.setAccessible(true);
                
//}
                return field.get(target);
            }

            
catch (Exception fe) {
                
if (logger.isDebugEnabled()) {
                    logger.debug(fe);
                }

            }

        }

        
return null;
    }


}
本站僅提供存儲服務,所有內(nèi)容均由用戶發(fā)布,如發(fā)現(xiàn)有害或侵權內(nèi)容,請點擊舉報
打開APP,閱讀全文并永久保存 查看更多類似文章
猜你喜歡
類似文章
xml轉換為java對象
asp.net 與datasnap交互 Demo
在struts2的Action中返回Ajax顯示需要的信息
org.springside.modules.utils.ReflectionUtils
通過java的反射機制實現(xiàn)Map、JavaBean、JSON的相互轉換工具類
WebSocket 獲取客戶端的IP
更多類似文章 >>
生活服務
分享 收藏 導長圖 關注 下載文章
綁定賬號成功
后續(xù)可登錄賬號暢享VIP特權!
如果VIP功能使用有故障,
可點擊這里聯(lián)系客服!

聯(lián)系客服