Hessian源码学习(二)
【客户端】
我们在客户端是如何使用hessian呢?
String url = "http://localhost:8080/Hello/hello";HessianProxyFactory factory = new HessianProxyFactory();IHello helloProxy = (IHello)factory.create(IHello.class, url);System.out.println(helloProxy.sayHello());
以上代码就可以实现hessian的远程调用了,但是这些究竟是怎么实现的呢,我们一步步分析。
factory.create(IHello.class, url); 通过 HessianProxyFactory(Hessian代理工厂)创建一个代理类,具体代码如下;
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(); 实际上是调用代理类的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.2 只支持参数个数不同的重载,后面版本才真正意义上的支持重载)if (! _factory.isOverloadEnabled()) {// 不要求重载,则什么都不做 }else if (args != null) 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());
以上是客户端整个调用远程服务的流程(细节未涉及),总结:整个hessian远程调用可以用以下一副图概括:
