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

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

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

    春風(fēng)博客

    春天里,百花香...

    導(dǎo)航

    <2008年9月>
    31123456
    78910111213
    14151617181920
    21222324252627
    2829301234
    567891011

    統(tǒng)計(jì)

    公告

    MAIL: junglesong@gmail.com
    MSN: junglesong_5@hotmail.com

    Locations of visitors to this page

    常用鏈接

    留言簿(11)

    隨筆分類(224)

    隨筆檔案(126)

    個(gè)人軟件下載

    我的其它博客

    我的鄰居們

    最新隨筆

    搜索

    積分與排名

    最新評(píng)論

    閱讀排行榜

    評(píng)論排行榜

    使用模板方法模式簡(jiǎn)化控制層類(Action)的設(shè)計(jì)

    在基于Model2的應(yīng)用中,控制層的類總會(huì)包含對(duì)業(yè)務(wù)層諸類的調(diào)用,業(yè)務(wù)層諸類不可避免的要產(chǎn)生各種異常,如果統(tǒng)一到控制層進(jìn)行處理的話會(huì)導(dǎo)致代碼變得龐大臃腫還有不少重復(fù),這種的例子在Web應(yīng)用中的Servlet和Action諸類中并不少見(jiàn)。

    如果我們使用模板方法模式(Template Method Pattern)將業(yè)務(wù)處理和異常處理分開(kāi),能有效簡(jiǎn)化控制層諸類的代碼,借用這種模式,我們可以把固定的異常處理代碼放在基類中,而讓子類來(lái)實(shí)現(xiàn)具體的業(yè)務(wù),如果執(zhí)行業(yè)務(wù)過(guò)程中出現(xiàn)異常如數(shù)據(jù)庫(kù)無(wú)法連接,用戶找不到等異常后,直接將異常拋出讓基類來(lái)處理,這樣做成功的把業(yè)務(wù)處理和異常處理分開(kāi)到了子類和基類兩種類中,涉及具體業(yè)務(wù)處理的子類代碼得到了很大的簡(jiǎn)化,更方便閱讀,修改和管理。

    具體請(qǐng)參考以下代碼:

    諸Action的基類,包含了所有的異常處理,它是一個(gè)抽象類,規(guī)定子類必需實(shí)現(xiàn)process函數(shù):
    package com.heyang.action.base;

    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;

    import org.apache.struts.action.Action;
    import org.apache.struts.action.ActionForm;
    import org.apache.struts.action.ActionForward;
    import org.apache.struts.action.ActionMapping;
    import org.springframework.dao.DataAccessResourceFailureException;
    import org.springframework.dao.DataIntegrityViolationException;
    import org.springframework.dao.InvalidDataAccessResourceUsageException;
    import org.springframework.dao.TypeMismatchDataAccessException;

    import com.heyang.domain.User;
    import com.heyang.exception.database.CannotFindRecordByIdException;
    import com.heyang.exception.database.OneIdMultiRecordException;
    import com.heyang.exception.user.CannotFindUserInSessionException;
    import com.heyang.exception.user.ErrorPswdException;

    /**
     * 各個(gè)Action的基類
     * 
    @author 何楊(heyang78@gmail.com)
     *
     * 
    @since 2008-8-29 上午09:00:48
     * 
    @version 1.00
     
    */

    public abstract class BizBaseAction extends Action {
        
    public ActionForward execute(ActionMapping mapping, ActionForm form,
                HttpServletRequest request, HttpServletResponse response)
                
    throws Exception {
            
            request.setCharacterEncoding(
    "UTF-8");
                    
            
    try{
                
    return process(mapping,form,request,response);
            }

            
    catch(CannotFindUserInSessionException ex){
                
    // 用戶名不存在
                request.setAttribute("msg""在session中找不到用戶,要執(zhí)行操作請(qǐng)先登錄");            
                
    return new ActionForward("/web/page/login.jsp");
            }
     
            
    catch(CannotFindRecordByIdException ex){
                
    // 用戶名不存在
                request.setAttribute("msg""用戶名不存在,請(qǐng)重新輸入");            
                
    return new ActionForward("/web/page/login.jsp");
            }
      
            
    catch(ErrorPswdException ex){
                
    // 用戶登錄密碼錯(cuò)誤
                request.setAttribute("msg""密碼錯(cuò)誤,請(qǐng)重新輸入");            
                
    return new ActionForward("/web/page/login.jsp");
            }

            
    catch(OneIdMultiRecordException ex){
                
    // 系統(tǒng)發(fā)生重大問(wèn)題,一個(gè)用戶名對(duì)應(yīng)著多條記錄
                request.setAttribute("feedbackTitle""系統(tǒng)發(fā)生重大問(wèn)題");
                request.setAttribute(
    "feedbackConcept""系統(tǒng)發(fā)生重大問(wèn)題,成員用戶名對(duì)應(yīng)著多條記錄,報(bào)告此錯(cuò)誤的郵件已經(jīng)發(fā)給系統(tǒng)管理員,請(qǐng)耐心等候處理。");
                
    return new ActionForward("/web/page/result.jsp");
            }
              
            
    catch(TypeMismatchDataAccessException ex){
                request.setAttribute(
    "feedbackTitle""Java類型和數(shù)據(jù)類型不匹配.");
                request.setAttribute(
    "feedbackConcept""錯(cuò)誤信息為"+ex.getMessage());
                
    return new ActionForward("/web/page/result.jsp");
            }

            
    catch(DataAccessResourceFailureException ex){
                request.setAttribute(
    "feedbackTitle""無(wú)法連接到數(shù)據(jù)庫(kù),請(qǐng)檢查數(shù)據(jù)庫(kù)連接是否正確.");
                request.setAttribute(
    "feedbackConcept""錯(cuò)誤信息為"+ex.getMessage());
                
    return new ActionForward("/web/page/result.jsp");
            }

            
    catch(DataIntegrityViolationException ex){
                request.setAttribute(
    "feedbackTitle""Insert或Update數(shù)據(jù)時(shí)違反了完整性.");
                request.setAttribute(
    "feedbackConcept""錯(cuò)誤信息為"+ex.getMessage());
                
    return new ActionForward("/web/page/result.jsp");
            }

            
    catch(InvalidDataAccessResourceUsageException ex){
                request.setAttribute(
    "feedbackTitle""使用錯(cuò)誤的SQL語(yǔ)句或數(shù)據(jù)訪問(wèn)關(guān)系型數(shù)據(jù)庫(kù).");
                request.setAttribute(
    "feedbackConcept""錯(cuò)誤信息為"+ex.getMessage());
                
    return new ActionForward("/web/page/result.jsp");
            }

            
    catch(Exception ex){
                request.setAttribute(
    "feedbackTitle""未知的錯(cuò)誤");
                request.setAttribute(
    "feedbackConcept""錯(cuò)誤信息為"+ex.getMessage());
                
    return new ActionForward("/web/page/result.jsp");
            }

        }

        
        
    /**
         * 留待子類實(shí)現(xiàn)業(yè)務(wù)
         * 
    @param mapping
         * 
    @param form
         * 
    @param request
         * 
    @param response
         * 
    @return
         * 
    @throws Exception
         
    */

        
    protected abstract ActionForward process(ActionMapping mapping, ActionForm form,
                HttpServletRequest request, HttpServletResponse response)
        
    throws Exception ;

        
        
    /**
         * 從Session中找出登錄用戶
         * 
    @param request
         * 
    @return
         * 
    @throws CannotFindUserInSessionException
         
    */

        
    protected User getUser(HttpServletRequest request) throws CannotFindUserInSessionException{
            
    // 從Session中取得用戶
            User user = (User) request.getSession().getAttribute("user");
            
    if (user == null{
                
    throw new CannotFindUserInSessionException("在session中找不到用戶");
            }

            
            
    return user;
        }

    }


    子類之一loginAction,只需實(shí)現(xiàn)簡(jiǎn)短的process函數(shù)即可,所有異常拋出由基類處理:
    package com.heyang.action;

    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;

    import org.apache.struts.action.ActionForm;
    import org.apache.struts.action.ActionForward;
    import org.apache.struts.action.ActionMapping;

    import com.heyang.action.base.BizBaseAction;
    import com.heyang.domain.User;
    import com.heyang.service.UserService;
    import com.heyang.util.ReqUtil;
    import com.heyang.util.SpringUtil;

    /**
     * 用于用戶登錄的Action
     * 
    @author 何楊(heyang78@gmail.com)
     *
     * 
    @since 2008-8-29 上午09:00:48
     * 
    @version 1.00
     
    */

    public final class LoginAction extends BizBaseAction {
        
    public ActionForward process(ActionMapping mapping, ActionForm form,
                HttpServletRequest request, HttpServletResponse response)
                
    throws Exception {
            request.setCharacterEncoding(
    "UTF-8");
            
            
    // 取得參數(shù)
            String name = ReqUtil.getFormProperty("name",form);
            String pswd 
    = ReqUtil.getFormProperty("pswd",form);
                
            
    // 取得Service
            UserService service=SpringUtil.getUserService();        
            
            
    // 取得用戶
            User user=service.getUser(name, pswd);
            request.getSession().setAttribute(
    "user", user);
            
    return new ActionForward("/ShowBlocks.do");
        }

    }

    這樣完成以后,對(duì)子類來(lái)說(shuō),只需要關(guān)心業(yè)務(wù)代碼即可,出現(xiàn)異常后的處理和轉(zhuǎn)向都由基類規(guī)定的模板方法完成,這正是模板方法模式給我們帶來(lái)的好處。有點(diǎn)疑惑的是,現(xiàn)在還不確定這樣做會(huì)有什么消極印象,如安全性或結(jié)構(gòu)方面的,大家要是覺(jué)得有問(wèn)題請(qǐng)不吝賜教。

    posted on 2008-09-01 11:51 sitinspring 閱讀(2219) 評(píng)論(8)  編輯  收藏 所屬分類: Object Orient ProgrammingSSH

    評(píng)論

    # re: 使用模板方法模式簡(jiǎn)化控制層類(Action)的設(shè)計(jì) 2008-09-01 14:14 zhuxing

    更多的公共代碼的放置問(wèn)題,骨架突出的成份小  回復(fù)  更多評(píng)論   

    # re: 使用模板方法模式簡(jiǎn)化控制層類(Action)的設(shè)計(jì) 2008-09-01 14:38 隔葉黃鶯

    現(xiàn)在流行的MVC框架,如 Struts1/Struts2/WebWork/Spring MVC 都能以配置的方式來(lái)處理異常,也不需在基類 Action 中處理。
    你的 Action 執(zhí)行方法只需往框架拋異常,配置一個(gè) ExeptionHandler 就會(huì)處理控制層拋出的異常,這樣的做法讓控制層和異常處理類解耦。
    不像你的 BaseAction 實(shí)際與異常處理綁定到一起了,我原來(lái)的項(xiàng)目也是會(huì)寫這么一個(gè) BaseAction,后來(lái)更細(xì)致了解一下所用的框架就會(huì)單獨(dú)寫一個(gè)異常處理類,配置給框架。  回復(fù)  更多評(píng)論   

    # re: 使用模板方法模式簡(jiǎn)化控制層類(Action)的設(shè)計(jì) 2008-09-01 15:04 zhuxing

    @隔葉黃鶯
    “尋道者”和你講的不是一個(gè)層面的問(wèn)題。“尋道者”講的是設(shè)計(jì)模式,你說(shuō)的框架使用。你這么比,樓主有可能會(huì)生氣。

    @隔葉黃鶯
    也斗膽接著聊一下你說(shuō)的那個(gè)問(wèn)題。從抽象層面講,我們?nèi)绻胍幚硪粋€(gè)行為的變化,一般需要干這幾件事情:
    抽象變化,封裝變化
    數(shù)據(jù)上下文
    控制上下文

    這種流行框架中的異常處理配置機(jī)制就真的好嗎,如果用戶想進(jìn)行自定義的控制下文呢(例如摟主文中的)???如果數(shù)據(jù)上下文變化較為頻繁呢???(當(dāng)然,這可能是由于起初對(duì)需求抽象不夠,對(duì)已知擴(kuò)展沒(méi)有做詳細(xì)分析)

    我們?cè)偾袚Q到另外一個(gè)角度來(lái)看這個(gè)問(wèn)題,任何一個(gè)框架肯定就是提供可復(fù)用的數(shù)據(jù)和行為。這種異常處理的配置機(jī)制暫且看作框架提供的行為支持吧。 那我可能會(huì)問(wèn)了?我一個(gè)業(yè)務(wù)處理過(guò)程本身就包含了異常處理,我干嗎再去配啊,而且給我分開(kāi)了,以后還要維護(hù)這個(gè)配置文件???

    這種異常配置的機(jī)制有它的好處,也有它的適用場(chǎng)景,再一個(gè)那就是取決于開(kāi)發(fā)者的嗜好....

    @隔葉黃鶯:我只是有興趣瞎評(píng)論一下,錯(cuò)誤請(qǐng)指正  回復(fù)  更多評(píng)論   

    # re: 使用模板方法模式簡(jiǎn)化控制層類(Action)的設(shè)計(jì) 2008-09-01 15:33 隔葉黃鶯

    @zhuxing
    樓主代碼實(shí)際用到 Struts,我才說(shuō)起 struts 框架來(lái),以及它能提供給我們的便利

    看樓主的基類 Action 其實(shí)是包含了多種業(yè)務(wù)的異常處理,作為樓主的替代方式,應(yīng)該配置一個(gè)異常處理類即可,不需要配置多個(gè),所以不涉及到要怎么去維護(hù)這個(gè)配置文件。如果分業(yè)務(wù)定義多個(gè)基類 Action 來(lái)處理異常,又何異于配置多個(gè)異常處理類呢?

    當(dāng)然,與業(yè)務(wù)非常密緊密的異常,可能放在統(tǒng)一異常處理類里不是很合適。不過(guò)要是考慮正常業(yè)務(wù)邏輯與異常流程分開(kāi)來(lái),丟給一個(gè) ExceptionHandler 也未嘗不可。

    如果數(shù)據(jù)上下文變化較為頻繁呢,這時(shí)候就要修改基類 Action 處理異常的代碼,這和修改異常處理類也沒(méi)多少分別。
      回復(fù)  更多評(píng)論   

    # re: 使用模板方法模式簡(jiǎn)化控制層類(Action)的設(shè)計(jì) 2008-09-01 15:50 尋道者

    @zhuxing
    @隔葉黃鶯

    兩位都談得很好啊,受益匪淺,本來(lái)我寫這個(gè)文章就是為了討論和驗(yàn)證想法的。只要是技術(shù)討論,大家暢所欲言吧。

      回復(fù)  更多評(píng)論   

    # re: 使用模板方法模式簡(jiǎn)化控制層類(Action)的設(shè)計(jì) 2008-09-01 16:12 zhuxing

    @隔葉黃鶯 @尋道者

    一個(gè)框架給我們提供了服務(wù)的同時(shí),肯定會(huì)給我們提供了相應(yīng)的限制。我覺(jué)得,很多時(shí)候在決定要使用一個(gè)開(kāi)源框架或者新的方法論(例如AOP)的時(shí)候,不但要看到框架的作用,也需要投入很大精力來(lái)分析一下框架的短板和限制。當(dāng)然,是基于我們的需求來(lái)分析,如果脫離這一點(diǎn),那就沒(méi)有意義了,純技術(shù)去分析一個(gè)框架可以當(dāng)作閑來(lái)無(wú)事時(shí)的消遣~_~  回復(fù)  更多評(píng)論   

    # re: 使用模板方法模式簡(jiǎn)化控制層類(Action)的設(shè)計(jì) 2008-09-01 17:46 隔葉黃鶯

    @zhuxing
    你的用語(yǔ)很職業(yè),只是我們需要切合這里的實(shí)際來(lái)討論問(wèn)題。  回復(fù)  更多評(píng)論   

    # re: 使用模板方法模式簡(jiǎn)化控制層類(Action)的設(shè)計(jì) 2008-09-01 18:03 zhuxing

    @隔葉黃鶯
    哈哈。
    回到實(shí)際,樓主文章中說(shuō)的主題和異常配置也有點(diǎn)遠(yuǎn),覺(jué)得樓主好像意在說(shuō)一個(gè)設(shè)計(jì)模式
      回復(fù)  更多評(píng)論   

    sitinspring(http://m.tkk7.com)原創(chuàng),轉(zhuǎn)載請(qǐng)注明出處.
    主站蜘蛛池模板: 亚洲国产成人精品久久| 国产亚洲一区二区三区在线观看| 日韩亚洲精品福利| 精品亚洲视频在线观看| 亚洲人成人网站色www| 亚洲国产一区在线| 91丁香亚洲综合社区| 老司机午夜性生免费福利| 久久精品无码专区免费| 24小时日本韩国高清免费| 四虎影院免费在线播放| 亚洲国产日韩在线观频| 亚洲精品国产成人专区| 一本色道久久综合亚洲精品蜜桃冫| 国产亚洲福利精品一区二区| 中文字幕免费播放| 五月婷婷在线免费观看| 国产小视频免费观看| 亚洲va中文字幕无码久久| 精品国产日韩久久亚洲| 一级一级毛片免费播放| **实干一级毛片aa免费| 免费国产高清视频| 日韩亚洲一区二区三区| 亚洲色大成网站www永久网站| 四虎精品免费永久免费视频| 亚洲一区二区三区免费观看| 亚洲高清最新av网站| 亚洲人成电影在线天堂| 真正全免费视频a毛片| 午夜无码A级毛片免费视频| 国产视频精品免费| 亚洲精品高清久久| 日本一区二区在线免费观看| 91精品视频在线免费观看| 国产jizzjizz免费看jizz| 一区二区三区亚洲| 成年网站免费入口在线观看 | 亚洲AV无码一区二区大桥未久 | 暖暖免费在线中文日本| 成人性生交视频免费观看|