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

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

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

    當柳上原的風吹向天際的時候...

    真正的快樂來源于創造

      BlogJava :: 首頁 :: 聯系 :: 聚合  :: 管理
      368 Posts :: 1 Stories :: 201 Comments :: 0 Trackbacks
    在交易系統的C/S體系中,C只負責數據的輸入和顯示,相當于MVC中的View部分,S負責數據的操作和持久化,兩者是通過WebService進行聯系的,具體來說聯系的方式是這樣:C端將指定S端負責處理的Service類名,具體負責處理的函數名和函數的參數打包成一個XML傳送到S端,S端解析后通過反射找到具體的函數進行處理,處理的結果會轉化成XML形式的字符串傳回。這就是設計梗概一中提到的內容。

    如果這個過程交給負責具體業務的程序員自行完成的話,那無疑會給系統帶來許多混亂和無序,程序員也無法將主要精力集中在業務上;另外,他們也無需了解每個細節是怎么完成的,他們真正需要的是框架提供好的接口,知道怎么調用取得結果就可以了。他們希望最好能像調用普通函數一樣調用S中的方法并取得想要的結果,舉例來說,如果客戶端需要查詢姓名以H開頭的所有雇員,他們只需調用一個search函數就能得到查詢出來的雇員集合,中間發生的組裝請求XML,WebService調用,業務處理,從數據庫查詢數據,將數據轉為XML傳回和在客戶端解析傳回的XML再變成領域對象集合等都應該由框架來完成。這并不過分,而是很合理的需求,就像RMI曾經就是這樣做的。

    那么,客戶端與服務器端的交互會有幾種形式呢,從業務上來說無外乎下面五種形式:
    1.調用S端的一個函數,只想知道這個函數是否正確運行了。典型例子如對象的刪除操作。
    2.調用S端的一個函數,想得到函數執行后返回的一個對象。典型例子如對象的添加操作,用戶需要取回添加好的對象的ID。
    3.調用S端的一個函數,想得到返回對象的集合列表。典型例子如對象的查詢。
    4.調用S端的一個函數,想得到分頁后的某一頁對象集合。典型例子如分頁查詢。
    5.調用S端的一個函數,只想得到一個字符串。典型例子如改變一種商品的目錄,得到某種商品的介紹文字等。
    框架需要做的,就是把這五種形式做成通用的函數提供給負責業務的程序員,讓他們僅需要這五個函數就能完成與WebService服務器的交互。這五種形式以第二種最為典型,也最為基礎,完成了它其它的就可以依樣畫葫蘆,下面請看具體過程:

    首先,規定具體函數的形制為
    public static BaseDomainObj fetchObject(String url,String serviceName,String mothodName,String[] args,Class<?> cls);
    公有靜態自不必說,BaseDomainObj是客戶端領域對象的基類,fetchObject是函數名,接下來是四個參數,前三個分別是WebService所在URL,服務器上服務類注冊在Spring上下文中的beanName,服務類具體的方法名,最后一個是取得對象的類型,在函數體中,會根據類型用反射生成一個實例,再通過實例的FromXML方法給實例的屬性賦值,完成后就得到了負責業務的程序員想要的結果。

    其次,fetchObject內部需要做的事情有:
    1.將serviceName,mothodName,args三項組合成一段XML文本。此項工作由WSRequest類完成。
    2.向位于url上的WebService服務器端發起請求,獲得返回的文本。此項工作由WSInvoker類來完成。
    3.將返回的文本轉化出來,這一步是要檢測服務器端函數執行是否順暢,有無拋出異常等。因為服務器端如果發生異常是無法通過WebService傳回的,只能變成文本后回傳,那么客戶端就需要解析一次,有問題就報出來,沒問題再往下走。這一步是堅決不能忽視的。
    4.通過反射得到對象,此時對象的屬性還是原始狀態,需要再通過反射注入相應的值,最后,客戶端需要的對象就產生了。

    具體的過程請參考下面的代碼:
    /**
     * 調用遠程WebService端,將返回的XML轉化為一個對象,最終返回.這種調用的典型例子是getById,add等
     * 
    @param url WebService所在URL
     * 
    @param serviceName 服務名,此名在appCtx.xml中定義
     * 
    @param mothodName 方法名
     * 
    @param args 方法的參數
     * 
    @param cls 要返回的對象類型
     * 
    @return
     
    */
    public static BaseDomainObj fetchObject(String url,String serviceName,String mothodName,String[] args,Class<?> cls){
        
    // 得到客戶端請求XML文本
        WSRequest request=new WSRequest(serviceName,mothodName,args);
        String requestXML
    =request.toXML();
        logger.info(
    "準備向位于'"+url+"'發送的請求XML為'"+requestXML+"'.");
        
        
    try{
            
    // 調用遠端WebService上的方法,得到返回的XML文本
            WSInvoker invoker=new WSInvoker(url);
            String responseXML
    =invoker.getResponseXML(requestXML);
            logger.info(
    "得到位于'"+url+"'響應XML為'"+responseXML+"'.");
            
            
    // 轉化響應
            WSResponse response=new WSResponse(responseXML);
            logger.info(response);
            
            
    // 如果在調用過程中如通不過檢測而被中斷的話
            if(response.isBreaked()){
                String errTxt
    ="遠程方法被中斷,具體原因是"+response.getRemark();
                logger.error(errTxt);
                
    throw new WSBreakException(errTxt+".(WSE05)");
            }
            
            
    // 如果在調用過程中出現異常的話
            if(response.hasException()){
                String errTxt
    ="調用遠程方法返回了異常,具體信息是"+response.getRemark();
                logger.error(errTxt);
                
    throw new WSException(errTxt+".(WSE04)");
            }
            
            
    try{
                
    // 通過反射得到對象
                BaseDomainObj obj= (BaseDomainObj)cls.newInstance();
                
                
    // 通過反射得到方法
                Method method = cls.getMethod("fromXML"new Class[] {String.class});
                
                
    // 通過反射調用對象的方法
                method.invoke(obj, new Object[] {response.getMethodResonseXML()});
                
                
    return obj;
            }
            
    catch(Exception ex){
                String errTxt
    ="無法將"+response.getMethodResonseXML()+"轉化為"+cls.getName()+"對象.(WSE06)";
                logger.error(errTxt);
                
    throw new WSException(errTxt);
            }
        }
        
    catch(MalformedURLException e){
            String errTxt
    ="無法調用'"+url+"'上的服務,因為它是畸形的.(WSE01)";
            logger.error(errTxt);    
            
    throw new WSException(errTxt);
        }
        
    catch(XFireRuntimeException e){
            String errTxt
    ="無法調用'"+url+"'上的服務.(WSE02)";
            logger.error(errTxt);    
            
    throw new WSException(errTxt);
        }
        
    catch(DocumentException e){
            String errTxt
    ="無法解析從服務器端'"+url+"'返回的XML文本.(WSE03)";
            logger.error(errTxt);    
            
    throw new WSException(errTxt);
        }
    }


    我們再看看通過關鍵的注入屬性值的fromXML函數做了些什么:
    public void fromXML(String xml) throws DocumentException{
        Document doc
    =DocumentHelper.parseText(xml);        
        
        Element root
    =doc.getRootElement();        
        List
    <Element> elms=root.elements();
        
        
    for(Element elm:elms){
            
    try {
                
    // 借助于BeanUtils,給對象的屬性賦值
                BeanUtils.setProperty(this,elm.getName(),elm.getText());
            } 
    catch (IllegalAccessException e) {
                e.printStackTrace();
            } 
    catch (InvocationTargetException e) {
                e.printStackTrace();
            }
        }
    }


    最后,我們可以看看負責業務的程序員需要書寫的代碼示例:
    public Tmp add(String name,String age,String salary,String picture){
        String url
    =CommonUtil.WebService_Url;
        String serviceName
    ="TmpService";
        String methodName
    ="add";
        String[] args
    =new String[]{name,age,salary,picture};
        
        
    try{
            
    return (Tmp)WSUtil.fetchObject(url, serviceName, methodName, args, Tmp.class);
        }
        
    catch(WSBreakException ex){
            DlgUtil.popupWarningDialog(ex.getMessage());
        }
        
    catch(WSException ex){
            DlgUtil.popupErrorDialog(ex.getMessage());
        }
        
        
    return null;
    }


    小結:
    一.負責業務程序員不需要了解的細節,框架應該將它們隱藏起來。
    二.負責業務程序員需要了解的接口,框架應該使它們盡量簡單。
    三.框架能做到的,就不該再讓負責業務的程序員再重復的發明車輪。
    posted on 2010-05-21 00:18 何楊 閱讀(198) 評論(0)  編輯  收藏

    只有注冊用戶登錄后才能發表評論。


    網站導航:
     
    主站蜘蛛池模板: 乱淫片免费影院观看| 亚洲一区二区三区无码国产| 欧亚一级毛片免费看| 免费涩涩在线视频网| 亚洲综合一区无码精品| 毛片a级毛片免费观看品善网| 亚洲另类春色校园小说| 免费看韩国黄a片在线观看| 中文字幕无码亚洲欧洲日韩| 最近中文字幕免费mv视频8| 亚洲乱人伦中文字幕无码| 国产美女精品久久久久久久免费 | 99精品视频在线免费观看| 亚洲五月激情综合图片区| 久久国产色AV免费观看| 亚洲a级在线观看| 天天看免费高清影视| 羞羞视频免费网站入口| 亚洲欧洲精品成人久久曰影片 | 亚洲AV无码国产精品永久一区| 成人免费毛片内射美女-百度| 亚洲综合一区国产精品| 全部免费a级毛片| 天黑黑影院在线观看视频高清免费| 亚洲日韩区在线电影| 亚洲女久久久噜噜噜熟女| 99视频在线免费| 日本亚洲精品色婷婷在线影院| 国产午夜鲁丝片AV无码免费| 狠狠色香婷婷久久亚洲精品| 国产在线观看免费不卡| 一区二区免费电影| 亚洲高清免费在线观看| 日日夜夜精品免费视频| 精品国产一区二区三区免费| 亚洲不卡影院午夜在线观看| 亚洲国产成人精品久久久国产成人一区二区三区综 | 97碰公开在线观看免费视频| 国产亚洲Av综合人人澡精品| 亚洲AV无码一区二区乱孑伦AS| 最新欧洲大片免费在线|