ALL is Well!

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

            BlogJava :: 首頁(yè) :: 新隨筆 :: 聯(lián)系 :: 聚合  :: 管理 ::
            30 隨筆 :: 23 文章 :: 71 評(píng)論 :: 0 Trackbacks

          本文為原創(chuàng),歡迎轉(zhuǎn)載,轉(zhuǎn)載請(qǐng)注明出處BlogJava

          在上一篇 Hessian構(gòu)建分布式系統(tǒng)應(yīng)用 的基礎(chǔ)上,我們對(duì)程序進(jìn)行改進(jìn)。
          現(xiàn)在有以下比較突出的問(wèn)題:
          a.如果hessian服務(wù)端我要做的業(yè)務(wù)很多,怎么辦?
          我要定義很多個(gè)接口,然后再寫(xiě)實(shí)現(xiàn)類(lèi),最煩的是還要配置它。
          我的設(shè)想是,hessian服務(wù)只提供一個(gè)歸口,再此對(duì)外的接口實(shí)現(xiàn)中反射調(diào)用具體的業(yè)務(wù)類(lèi)。

          b.客戶(hù)端在調(diào)用時(shí),每次調(diào)用遠(yuǎn)程接口都要用以下代碼嗎:

          String url = "http://localhost:8080/HessianService/remote/service";
          HessianProxyFactory factory 
          = new HessianProxyFactory();
          ServiceRemote rmt 
          = (ServiceRemote) factory.create(ServiceRemote.class, url);


          顯然是不需要的。
          我們可以通過(guò)加入緩存的方式對(duì)其進(jìn)行改良,我們也可以通過(guò)Spring在客戶(hù)端管理它。

          一、完善hessian服務(wù)端實(shí)現(xiàn):
          1.首先修改ServiceRemote接口:

          package com.al;

          import java.util.Map;

          @SuppressWarnings(
          "unchecked")
          public interface ServiceRemote  {
              
          public Map callService(String target, Map inputMap) throws Exception;
          }

          callService為統(tǒng)一入口,在此做如下約定:
          1)target字符串為要調(diào)用的service的完整類(lèi)路徑+要調(diào)用的方法。
          2)service的方法均用以下方法簽名:
          public Map ***(Map inputMap);
          入?yún)镸ap,返回值也為Map,基本可以滿(mǎn)足所有情況了。(至少入?yún)镸ap,很適合調(diào)用iBatis來(lái)對(duì)DB進(jìn)行操作。)

          2.修改接口實(shí)現(xiàn)類(lèi)Service,此類(lèi)不做具體業(yè)務(wù),而是反射調(diào)用具體業(yè)務(wù)類(lèi):

          package com.al;

          import java.lang.reflect.Method;
          import java.util.Map;

          import org.apache.commons.beanutils.MethodUtils;
          import org.apache.commons.lang.StringUtils;

          @SuppressWarnings(
          "unchecked")
          public class Service implements ServiceRemote {

              
          public Map callService(String target, Map inputMap) throws Exception {
                  String className 
          = StringUtils.substringBeforeLast(target, ".");
                  String methodName 
          = StringUtils.substringAfterLast(target, ".");
                  Class serviceClass 
          = loadClass(className);
                  Method method 
          = getMethod(serviceClass, methodName, Map.class);
                  
          // 提供訪(fǎng)問(wèn)效率
                  method.setAccessible(true);
           
          // 調(diào)用具體業(yè)務(wù)類(lèi)
                  return (Map) method.invoke(serviceClass.newInstance(), inputMap);
              }

              
              
          private static <T> Class<T> loadClass(String className) throws ClassNotFoundException {
                      
          return (Class<T>) getClassLoader().loadClass(className);
              }

              
              
          private static ClassLoader getClassLoader() {
                  
          return Thread.currentThread().getContextClassLoader();
              }

              
              
          private static Method getMethod(Class<?> cls, String name, Class<?> parameterTypes) {
                  
          return MethodUtils.getAccessibleMethod(cls, name, parameterTypes);
              }

          }

           

          3.舉個(gè)例子,服務(wù)端提供業(yè)務(wù)類(lèi)DisplayUserService.java

          package com.al.service;

          import java.util.HashMap;
          import java.util.Map;

          @SuppressWarnings(
          "unchecked")
          public class DisplayUserService {
              
          public static final String selectUsers = "com.al.service.DisplayUserService.selectUsers";
              
          public static final String deleteUser = "com.al.service.DisplayUserService.deleteUser";
              
              
          public Map selectUsers(Map inputMap) {
                  Map ret 
          = new HashMap();
                  
          // 數(shù)據(jù)庫(kù)操作取得用戶(hù)列表 省略
                  ret.put("User""User");
                  
          return ret;
              }

              
              
          public Map deleteUser(Map inputMap) {
                  
          // 數(shù)據(jù)庫(kù)操作取得用戶(hù)列表 省略
                  return null;
              }

          }


          所有其他配置不變,請(qǐng)參考上一篇 Hessian構(gòu)建分布式系統(tǒng)應(yīng)用 。


          二、客戶(hù)端代碼的修改:
          1.加入spring進(jìn)行管理:
          application.xml

          <?xml version="1.0" encoding="UTF-8"?>
          <!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans.dtd">
          <beans>
              
          <bean id="serviceRemote" class="org.springframework.remoting.caucho.HessianProxyFactoryBean">
                  
          <property name="serviceUrl" value="http://localhost:8080/HessianService/remote/service" />
                  
          <property name="serviceInterface" value="com.al.ServiceRemote" />
              
          </bean>
          </beans>

           

          2.客戶(hù)端如下調(diào)用即可:

          package com.ai.client;

          import org.springframework.context.support.ClassPathXmlApplicationContext;

          import com.al.ServiceRemote;
          import com.al.service.DisplayUserService;

          public class ClientTest {
              
          public static void main(String[] args) throws Exception {
                  ClassPathXmlApplicationContext cxt 
          = new ClassPathXmlApplicationContext("application.xml");
                  ServiceRemote rmt 
          = (ServiceRemote)cxt.getBean("serviceRemote");
                  System.out.println(rmt.callService(DisplayUserService.selectUsers, 
          null));
              }

          }


          另外一種方法是自己實(shí)現(xiàn)緩存。
          也就是第一次調(diào)用遠(yuǎn)程代碼時(shí)生成ServiceRemote對(duì)象,將其保存在靜態(tài)的容器(HashMap)中,
          每次準(zhǔn)備調(diào)用此遠(yuǎn)程代碼時(shí),先判斷容器中是否有ServiceRemote對(duì)象,有則直接將其取出并使用即可,要注意的就是在這個(gè)容器上的同步問(wèn)題。
          具體實(shí)現(xiàn)就不做了,很簡(jiǎn)單。

          在項(xiàng)目中,對(duì)于客戶(hù)端代碼來(lái)講,還是有許多工作要做的:
          1) 如果我們要調(diào)用多個(gè)遠(yuǎn)程服務(wù)怎么辦?
          我們要提供一個(gè)統(tǒng)一調(diào)用,將遠(yuǎn)程調(diào)用的動(dòng)作封裝起來(lái),讓使用的人不知道自己調(diào)用了不同的遠(yuǎn)程服務(wù)。
          只要調(diào)用某個(gè)方法、傳入?yún)?shù)即可。

          2) 如何方便開(kāi)發(fā)員調(diào)試遠(yuǎn)程的服務(wù)代碼?
          在做分布式系統(tǒng)開(kāi)發(fā)的時(shí)候,如果每修改一下應(yīng)用層的service,就要對(duì)其進(jìn)行發(fā)布,然后再去調(diào)用看是否已OK,那效率會(huì)很低。

          3) 如何管理多方調(diào)用的遠(yuǎn)程服務(wù)?

          4) 如何提高遠(yuǎn)程調(diào)用的效率?
          是否可以通過(guò)對(duì) 對(duì)象進(jìn)行緩存、方法是否也可以緩存?甚至是對(duì)調(diào)用結(jié)果進(jìn)行緩存?

          5) 等等..
          這些在具體的項(xiàng)目中都是不得不考慮的問(wèn)題。以后再慢慢討論吧。

          posted on 2010-10-17 22:10 李 明 閱讀(1711) 評(píng)論(1)  編輯  收藏 所屬分類(lèi): J2EESpring

          評(píng)論

          # re: Hessian構(gòu)建分布式系統(tǒng)應(yīng)用[續(xù)][未登錄](méi) 2012-08-11 15:07 哈哈
          目前我正考慮類(lèi)似的方式構(gòu)建一個(gè)系統(tǒng)出現(xiàn)了一下問(wèn)題:
          1.如你所說(shuō),如果只采用一個(gè)暴露接口,當(dāng)訪(fǎng)問(wèn)量比較大時(shí)是不是有性能問(wèn)題呢?
          2.服務(wù)端的業(yè)務(wù)異常信息如何返回給客戶(hù)端?比如,當(dāng)Insert一條數(shù)據(jù),ID重復(fù),目前我是返回一個(gè)錯(cuò)誤碼給客戶(hù)端,客戶(hù)端根據(jù)錯(cuò)誤碼得到相應(yīng)信息


          希望多多交流  回復(fù)  更多評(píng)論
            

          主站蜘蛛池模板: 凉城县| 喜德县| 宁津县| 凯里市| 长阳| 株洲县| 方山县| 平山县| 宝山区| 吉林市| 惠来县| 黄石市| 通海县| 丘北县| 水城县| 广州市| 东辽县| 军事| 大关县| 德清县| 阿图什市| 岳阳县| 安国市| 保山市| 柳林县| 武胜县| 凌源市| 墨玉县| 咸宁市| 治多县| 乌拉特前旗| 上高县| 油尖旺区| 阳江市| 玛沁县| 云阳县| 肃南| 天水市| 鹤岗市| 灵石县| 桂平市|