个人博客: 戳我,戳我
先扯一扯
前一篇博文Hessian通信案例(java)简单实现了Java版的Hessian客户端和服务端的通信,总体看来,实现起来比较简单,整个基于Hessian的远程调用过程也显得很方便。但是知其然还要知其所以然,Hessian的底层是怎么实现远程调用的?是怎么序列化的?又是怎么反序列化的?又是如何通信的?
还记得吗
下面这段代码你还记得吗?
String url = "http://localhost:8080/hessian_server/ServerMachineTest";
HessianProxyFactory factory = new HessianProxyFactory();
IBasic basic = (IBasic) factory.create(IBasic.class, url);
String helloreturn = basic.hello();
上面这段代码就是前一篇博文中实现的客户端的代码,实现远程过程调用就短短的四行代码,如此简单。但是new HessianProxyFactory()是做什么的?factory.create()又是怎么实现的?
一层层的剥去外衣
项目姿势微调
为了探究new HessianProyFactory()具体实现了什么,需要对之前博文中实现的案例进行一点调整。案例中是直接导入了hessian-4.0.7.jar作为lib库的方式,为了在Eclipse中进行单步调试,需要用源码(hessian-4.0.7-src.jar)来替代这个jar包。这里需要注意的是版本,可能会出现兼容性的问题,具体情况可以试错。
导入源码包替换了jar包之后的效果:
client包主要是client端使用的功能,里面就是动态代理和http连接等操作,io包则是处理序列化。
这里需要注意的是,可能会出现一些错误,可能需要添加commons-io-2.4.jar这个包以及Tomcat的runtime环境。具体的话自行解决。
调整成这样后,启动Tomcat,启动Hessian服务端就可以对客户端进行单步调试了!O(∩_∩)O哈哈~
启动Hessian服务端
启动Hessian服务端后先进行下测试,运行刚刚调整过的Hessian客户端,看看有没有出错?正常情况会出现下面的结果:
接下来就可以对客户端进行单步调试了。
单步调试
在Eclipse中进行代码调试很方便,要在哪一行设置断点,只需要在行首进行双击,就可以看到一个圆点。F11(Debug),F5(step into),F6(step over)。
HessianProxyFactory factory = new HessianProxyFactory();
IBasic basic = (IBasic) factory.create(IBasic.class, url);
String helloreturn = basic.hello();
前两句没什么特殊的,new了一个动态代理工厂,这个工厂负责调用底层的序列化方法进行序列化;creat()函数根据定义好的接口函数以及设置好的服务端的地址进行一些处理。真正实现远程调用的是第三句代码,如下图,我在String helloreturn = basic.hello()这句代码设置断点。,启动调试,可以看到进入到了一个函数invoke()。
public Object invoke(Object proxy, Method method, Object []args)
throws Throwable
{
String mangleName;
synchronized (_mangleMap) {
mangleName = _mangleMap.get(method);
}
if (mangleName == null) {
String methodName = method.getName();
Class<?> []params = method.getParameterTypes();
// equals and hashCode are special cased
if (methodName.equals("equals")
&& params.length == 1 && params[0].equals(Object.class)) {
Object value = args[0];
if (value == null || ! Proxy.isProxyClass(value.getClass()))
return Boolean.FALSE;
Object proxyHandler = Proxy.getInvocationHandler(value);
if (! (proxyHandler instanceof HessianProxy))
return Boolean.FALSE;
HessianProxy handler = (HessianProxy) proxyHandler;
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 +