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

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

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

    春風博客

    春天里,百花香...

    導(dǎo)航

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

    統(tǒng)計

    公告

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

    Locations of visitors to this page

    常用鏈接

    留言簿(11)

    隨筆分類(224)

    隨筆檔案(126)

    個人軟件下載

    我的其它博客

    我的鄰居們

    最新隨筆

    搜索

    積分與排名

    最新評論

    閱讀排行榜

    評論排行榜

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

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

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

    具體請參考以下代碼:

    諸Action的基類,包含了所有的異常處理,它是一個抽象類,規(guī)定子類必需實現(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;

    /**
     * 各個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í)行操作請先登錄");            
                
    return new ActionForward("/web/page/login.jsp");
            }
     
            
    catch(CannotFindRecordByIdException ex){
                
    // 用戶名不存在
                request.setAttribute("msg""用戶名不存在,請重新輸入");            
                
    return new ActionForward("/web/page/login.jsp");
            }
      
            
    catch(ErrorPswdException ex){
                
    // 用戶登錄密碼錯誤
                request.setAttribute("msg""密碼錯誤,請重新輸入");            
                
    return new ActionForward("/web/page/login.jsp");
            }

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

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

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

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

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

        }

        
        
    /**
         * 留待子類實現(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,只需實現(xià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");
        }

    }

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

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

    評論

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

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

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

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

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

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

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

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

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

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

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

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

    @zhuxing
    樓主代碼實際用到 Struts,我才說起 struts 框架來,以及它能提供給我們的便利

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

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

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

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

    @zhuxing
    @隔葉黃鶯

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

      回復(fù)  更多評論   

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

    @隔葉黃鶯 @尋道者

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

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

    @zhuxing
    你的用語很職業(yè),只是我們需要切合這里的實際來討論問題。  回復(fù)  更多評論   

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

    @隔葉黃鶯
    哈哈。
    回到實際,樓主文章中說的主題和異常配置也有點遠,覺得樓主好像意在說一個設(shè)計模式
      回復(fù)  更多評論   

    sitinspring(http://www.tkk7.com)原創(chuàng),轉(zhuǎn)載請注明出處.
    主站蜘蛛池模板: 亚洲精品乱码久久久久久V| 免费高清小黄站在线观看 | 亚洲国产精品成人精品无码区 | 国产乱子精品免费视观看片| 久久亚洲色一区二区三区| 国产精品视频全国免费观看| 亚洲欧洲国产视频| 好吊妞在线成人免费| 日韩免费无码一区二区三区| 精品无码一级毛片免费视频观看| 亚洲最大av资源站无码av网址| 久久亚洲AV午夜福利精品一区| 亚洲熟伦熟女新五十路熟妇| 日韩激情无码免费毛片| 精品国产污污免费网站入口在线 | 日韩插啊免费视频在线观看| 国产精品青草视频免费播放| 免费无码国产V片在线观看| 国产av天堂亚洲国产av天堂| 全亚洲最新黄色特级网站| 精品国产免费一区二区三区香蕉 | 中文字幕不卡免费高清视频| 久久丫精品国产亚洲av| 日本h在线精品免费观看| 九一在线完整视频免费观看| 亚洲精品不卡视频| 久久亚洲中文字幕精品有坂深雪| 亚洲av无码专区在线播放| 亚洲成a人片在线观看无码专区| 亚洲欧洲无码AV电影在线观看 | 亚洲中文字幕无码一区| 国产在线a免费观看| 国产大片免费网站不卡美女| 亚洲精品在线免费观看| 亚洲人成免费网站| 69av免费观看| www.黄色免费网站| a毛片免费全部在线播放**| 亚洲AV无码AV吞精久久| 亚洲美女人黄网成人女| 亚洲愉拍99热成人精品热久久|