`
DiaoCow
  • 浏览: 242114 次
  • 性别: Icon_minigender_1
  • 来自: 南京
社区版块
存档分类
最新评论

Hessian源码学习(二)客户端

阅读更多
【客户端】

我们在客户端是如何使用hessian呢?
String url = "http://localhost:8080/Hello/hello";

HessianProxyFactory factory = new HessianProxyFactory();

// IHello为调用的服务接口,url为hessian服务url
IHello helloProxy = (IHello)factory.create(IHello.class, url);

System.out.println(helloProxy.sayHello());

以上代码就可以进行Hessian的远程调用了,但是这些究竟是怎么实现的呢,我们一步步分析(参考源码版本3.0.13)。


factory.create(IHello.class, url);

通过 HessianProxyFactory(Hessian代理工厂)创建一个代理类(采用JDK自带的动态代理),具体代码如下;
public Object create(Class api, String urlName)
    throws MalformedURLException
{
	return create(api, urlName, Thread.currentThread().getContextClassLoader());
}

public Object create(Class api, String urlName, ClassLoader loader)
    throws MalformedURLException
{
    URL url = new URL(urlName);

    // HessianProxy implements InvocationHandler 
    HessianProxy handler = new HessianProxy(this, url);  

    return Proxy.newProxyInstance(api.getClassLoader(),
                  new Class[] { api, HessianRemoteObject.class }, handler);
}


helloProxy.sayHello();

实际上是调用代理类HessianProxy的invoke方法,我们具体看下代码:
// 获取调用的方法名以及方法参数类型
String methodName = method.getName();
Class []params = method.getParameterTypes();

//对于以下方法直接执行本地调用而不是远程调用
if (methodName.equals("equals") &&
    params.length == 1 && params[0].equals(Object.class)) {
    Object value = args[0];
	if (value == null || ! Proxy.isProxyClass(value.getClass()))
        return new Boolean(false);

    HessianProxy handler = (HessianProxy) Proxy.getInvocationHandler(value);
	return new Boolean(_url.equals(handler.getURL()));
	}
else if (methodName.equals("hashCode") && params.length == 0)
  return new Integer(_url.hashCode());
else if (methodName.equals("getHessianType"))
  return proxy.getClass().getInterfaces()[0].getName();
else if (methodName.equals("getHessianURL"))
  return _url.toString();
else if (methodName.equals("toString") && params.length == 0)
  return "[HessianProxy " + _url + "]";
 

// 判断客户端是否要求支持重载(即客户端是否设置factory.setOverloadEnabled(true); 
//注:3.0.13 只支持参数个数不同的重载,后面版本才真正意义上的支持重载)
if (! _factory.isOverloadEnabled()) {
	// 不要求重载,则什么都不做
    }
else if (args != null)
    // 若支持重载,则目标方法名格式为:method名 + "__" + method参数个数
    methodName = methodName + "__" + args.length;
else
    methodName = methodName + "__0";
   
// 执行远程调用(建立http链接,设置一些http header, 序列化方法名和方法参数,执行http请求...)
conn = sendRequest(methodName, args);

// 从输入流中读取远程调用结果并返回给客户端
is = conn.getInputStream();
AbstractHessianInput in = _factory.getHessianInput(is);
return in.readReply(method.getReturnType());


总结

通过上面的代码分析,我们可以看到:

1.客户端如何进行Hessian远程调用,它的原理是什么;

2.如果要支持方法重载,客户端如何设置;


整个hessian远程调用可以用以下一副图概括:



下一篇文章我们将重点来看下Hessian的序列化实现,这才是Hessian让人激动的地方!
  • 大小: 29 KB
0
3
分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics