<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    ALL is Well!

    敏捷是一條很長的路,摸索著前進(jìn)著

      BlogJava :: 首頁 :: 新隨筆 :: 聯(lián)系 :: 聚合  :: 管理 ::
      30 隨筆 :: 23 文章 :: 71 評論 :: 0 Trackbacks
    本文為原創(chuàng),歡迎轉(zhuǎn)載,轉(zhuǎn)載請注明出處BlogJava。

    chain:基本用途是構(gòu)造成一條動作鏈。前一個Action將控制權(quán)轉(zhuǎn)交給后一個Action,而前一個Action的狀態(tài)在后一個Action里仍然保持著。
    我現(xiàn)在有一個場景,F(xiàn)irstAction 通過chain的方式,將控制權(quán)交給 SecondAction。FirstAction對應(yīng)的頁面代碼為first.ftl,SecondAction對應(yīng)的頁面代碼為second.ftl。
    假設(shè)我們的FirstAction如下定義:
    public class FirstAction extends ActionSupport{

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

        
    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)過調(diào)試,發(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前判斷一下,當(dāng)前Action是否需要從前面的Action實例中獲取數(shù)據(jù)。

    這個可以通過注解的方式告訴攔截器,當(dāng)前的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)為當(dāng)前Action、緊接著(index = 1) 為前置Action
            if (root == null || root.size() <= 2{
                
    return invocation.invoke();
            }


            
    // 當(dāng)前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);

                    
    // 取得對應(yīng)字段的值
                    Object value = ReflectionUtils.getFieldValue(srcAction, srcAction.getClass(), field.getName());
                    
    // 設(shè)定值
                    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());
                
    // 取得對應(yīng)字段的值 則返回
                
    // 問題:如果前置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
    }

    當(dāng)在執(zhí)行SecondAction之前,攔截器會去查找FirstAction,是否有 user 對象,有則將值拷貝到 SecondAction 中。
    ChainTransParam 注解 允許輸入?yún)?shù)名,沒有輸入則默認(rèn)根據(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;
        }


    }
    posted on 2010-11-19 17:25 李 明 閱讀(5330) 評論(2)  編輯  收藏 所屬分類: Struts2

    評論

    # re: 基于Struts2 Result Type為chain 的Action之間數(shù)據(jù)傳遞 2010-11-21 19:32 濤濤
    很不錯,值得學(xué)習(xí)  回復(fù)  更多評論
      

    # re: 基于Struts2 Result Type為chain 的Action之間數(shù)據(jù)傳遞 2010-11-24 12:04 dfasssssssssssssssssssssssssssssssssssssssssssssss
    fadsfasd  回復(fù)  更多評論
      

    主站蜘蛛池模板: 77777亚洲午夜久久多喷| 久久精品国产精品亚洲精品| 日韩免费视频网站| 成年女人毛片免费观看97| 日韩毛片免费无码无毒视频观看| 黄页网站在线观看免费高清| 免费A级毛片无码无遮挡内射| 国产1024精品视频专区免费| 女人18毛片a级毛片免费视频| 性感美女视频在线观看免费精品 | 久久久久成人片免费观看蜜芽| 华人在线精品免费观看| 人人玩人人添人人澡免费| 999久久久免费精品播放| 曰批全过程免费视频网址| 性做久久久久久久免费看| 成年人性生活免费视频| 国产成人免费手机在线观看视频| 免费99热在线观看| 亚洲精品无码不卡在线播HE | jizzjizz亚洲| 亚洲精品中文字幕乱码三区 | AV在线亚洲男人的天堂| 国产亚洲av片在线观看播放 | 国产亚洲精品a在线无码| 777亚洲精品乱码久久久久久 | 亚洲一区二区在线视频| 亚洲综合色7777情网站777| 亚洲av永久无码精品网址| 一级中文字幕免费乱码专区| 免费无码作爱视频| 国产免费一区二区三区| 日本高清色本免费现在观看| 亚洲综合精品香蕉久久网| 亚洲欧洲日产国码www| 噜噜综合亚洲AV中文无码| 久久一区二区免费播放| 曰曰鲁夜夜免费播放视频 | 免费A级毛片无码A∨中文字幕下载| 在线观看无码AV网站永久免费| 免费大片在线观看网站|