[转载]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) 等等..这些在具体的项目中都是不得不考虑的问题。之后再慢慢讨论吧。

相关文章
相关标签/搜索