[轉載]Hessian構建分佈式系統應用 2

如今有如下比較突出的問題:
a.若是hessian服務端我要作的業務不少,怎麼辦?
我要定義不少個接口,而後再寫實現類,最煩的是還要配置它。
個人設想是,hessian服務只提供一個歸口,再此對外的接口實現中反射調用具體的業務類。
html

b.客戶端在調用時,每次調用遠程接口都要用如下代碼嗎:java

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

 

顯然是不須要的。
咱們能夠經過加入緩存的方式對其進行改良,咱們也能夠經過Spring在客戶端管理它。web

1、完善hessian服務端實現:
1.首先修改ServiceRemote接口:spring

package com.al;
 
 import java.util.Map;
 
 @SuppressWarnings("unchecked")
public interface ServiceRemote  {
     public Map callService(String target, Map inputMap) throws Exception;
 }

 

callService爲統一入口,在此作以下約定:
1)target字符串爲要調用的service的完整類路徑+要調用的方法。
2)service的方法均用如下方法簽名:
public Map ***(Map inputMap);
入參爲Map,返回值也爲Map,基本能夠知足全部狀況了。(至少入參爲Map,很適合調用iBatis來對DB進行操做。)數據庫

2.修改接口實現類Service,此類不作具體業務,而是反射調用具體業務類:apache

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);
         // 提供訪問效率
         method.setAccessible(true);
  // 調用具體業務類
         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.舉個例子,服務端提供業務類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();
         // 數據庫操做取得用戶列表 省略
         ret.put("User", "User");
         return ret;
     }
     
    public Map deleteUser(Map inputMap) {
         // 數據庫操做取得用戶列表 省略
         return null;
     }
 }

 

 

全部其餘配置不變,請參考上一篇 Hessian構建分佈式系統應用 。app


2、客戶端代碼的修改:
1.加入spring進行管理:
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.客戶端以下調用便可:post

 

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));
     }
 }

 

 

另一種方法是本身實現緩存。
也就是第一次調用遠程代碼時生成ServiceRemote對象,將其保存在靜態的容器(HashMap)中,
每次準備調用此遠程代碼時,先判斷容器中是否有ServiceRemote對象,有則直接將其取出並使用便可,要注意的就是在這個容器上的同步問題。
具體實現就不作了,很簡單。

在項目中,對於客戶端代碼來說,仍是有許多工做要作的:
1) 若是咱們要調用多個遠程服務怎麼辦?
咱們要提供一個統一調用,將遠程調用的動做封裝起來,讓使用的人不知道本身調用了不一樣的遠程服務。
只要調用某個方法、傳入參數便可。

2) 如何方便開發員調試遠程的服務代碼?
在作分佈式系統開發的時候,若是每修改一下應用層的service,就要對其進行發佈,而後再去調用看是否已OK,那效率會很低。

3) 如何管理多方調用的遠程服務?

4) 如何提升遠程調用的效率?
是否能夠經過對 對象進行緩存、方法是否也能夠緩存?甚至是對調用結果進行緩存?

5) 等等..這些在具體的項目中都是不得不考慮的問題。之後再慢慢討論吧。

相關文章
相關標籤/搜索