Hessian在客户端一块采用Proxy模式,当客户端调用远程接口时,HessianProxy会代理这个动作,在invoke方法中,把客户端请求的方法和参数序列化为预订格式的输出流,主要流程如下图所示:
下面我将详细解析一下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 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 + "]";
if (! _factory.isOverloadEnabled())
mangleName = method.getName();
else
mangleName = mangleName(method);
synchronized (_mangleMap) {
_mangleMap.put(method, mangleName);
}
}
......
}
这是invoke的开头,主要干的事情是把methodName缓存起来和过滤一些特殊调用,java反射是个比较耗性能的操作,把methodName缓存起来可以避免每次调用都要从method里得到methodName。另外,对equals、hashCode、getHessianType、getHessianURL等特殊方法的远程调用,HessianProxy不会走远程调用,而是直接返回。
接着往下看:
public Object invoke(Object proxy, Method method, Object []args)
throws Throwable
{
......
InputStream is = null;
URLConnection conn = null;
HttpURLConnection httpConn = null;
try {
conn = sendRequest(mangleName, args);
......
} catch (HessianProtocolException e) {
throw new HessianRuntimeException(e);
} finally {
......
}
}
这段主要是把方法名和参数序列化为网络输出流,并做网络请求,具体逻辑包装在sendRequest方法中:
protected URLConnection sendRequest(String methodName, Object []args)
throws IOException
{
URLConnection conn = null;
conn = _factory.openConnection(_url);
boolean isValid = false;
try {
// Used chunked mode when available, i.e. JDK 1.5.
if (_factory.isChunkedPost() && conn instanceof HttpURLConnection) {
try {
HttpURLConnection httpConn = (HttpURLConnection) conn;
httpConn.setChunkedStreamingMode(8 * 1024);
} catch (Throwable e) {
}
}
addRequestHeaders(conn);
OutputStream os = null;
try {
os = conn.getOutputStream();
} catch (Exception e) {
throw new HessianRuntimeException(e);
}
if (log.isLoggable(Level.FINEST)) {
PrintWriter dbg = new PrintWriter(new LogWriter(log));
os = new HessianDebugOutputStream(os, dbg);
}
AbstractHessianOutput out = _factory.getHessianOutput(os);
out.call(methodName, args);
out.flush();
isValid = true;
return conn;
} finally {
if (! isValid && conn instanceof HttpURLConnection)
((HttpURLConnection) conn).disconnect();
}
}
sendRequest的主要流程是先初始化网络连接,然后用AbstractHessianOutput包装网络输出流,调用AbstractHessianOutput.call(methodName, args)完成网络输出,这个方法的细节会在hessian io的源码解析中详细分析。
下面接着看invoke方法:
public Object invoke(Object proxy, Method method, Object []args)
throws Throwable
{
......
is = conn.getInputStream();
AbstractHessianInput in = _factory.getHessianInput(is);
in.startReply();
Object value = in.readObject(method.getReturnType());
if (value instanceof InputStream) {
value = new ResultInputStream(httpConn, is, in, (InputStream) value);
is = null;
httpConn = null;
}
else
in.completeReply();
......
}
这一段主要是把输入流中取得返回值,具体是用AbstractHessianInput包装网络输入流,然后调用AbstractHessianInput.readObject从网络流中反序列化到实际返回值。
分享到:
相关推荐
《Hessian源码分析与Hack:携带远程调用端信息》 Hessian作为一种轻量级的RPC(远程过程调用)框架,因其高效、简洁的二进制协议,被广泛应用于构建Web服务。然而,在实际应用中,有时我们需要获取到远程调用端的IP...
总结一下,Hessian的源码分析主要关注客户端的`HessianProxy`和服务器端的`HessianSkeleton`这两个核心类。它们分别负责客户端的调用代理和服务器端的请求处理。源码中包含了方法名缓存、特殊方法的本地处理、以及...
**五、源码分析** 对于深入理解Hessian的工作机制,阅读和分析源码是必不可少的。Caucho Technology提供了Hessian的开源实现,开发者可以通过阅读源码了解其内部细节,如序列化和反序列化的具体实现、类型转换逻辑...
在【标签】中,"源码"可能指的是查看或分析Hessian协议的底层实现,这对于理解其工作原理和优化性能非常有帮助。"工具"可能指的是使用Hessian相关的开发工具或框架,例如HessianProxyFactory、HessianServlet等。 ...
在源码分析方面,理解Hessian的内部工作机制是提升开发技能的重要步骤。通过阅读和分析Hessian的源码,我们可以了解其如何编码和解码各种数据类型,以及如何优化序列化和反序列化的过程。这对于优化自定义序列化逻辑...
Hessian是一种二进制协议,它允许在不同的编程语言之间进行高效的远程方法调用(RPC)。...通过分析和实践这些示例代码,你可以更好地掌握Hessian的工作原理和使用方式,为你的跨语言项目打下坚实的基础。
Hessian的源码分析可以帮助我们更深入地理解其工作原理。Hessian服务端的序列化和反序列化过程、HTTP请求处理以及异常处理等都是关键部分。而Spring框架如何与Hessian进行集成,包括服务注册、请求处理和代理创建等...
《深入解析Hessian 4.0.51源码》 Hessian,作为一个高效轻量级的二进制Web服务协议,广泛应用于分布式系统中,它允许开发者...对于想深入理解分布式通信机制的开发者来说,研究Hessian源码无疑是一次宝贵的学习机会。
通过分析和实践这些源码,开发者可以深入理解如何在自己的项目中集成和使用Hessian。 6. **PPT材料**:二进制Web服务Hessian.ppt很可能是讲座的幻灯片,其中可能涵盖了Hessian的基础概念、工作流程、优缺点以及实战...
至于"工具",有一些工具可以帮助开发者测试和调试Hessian服务,例如,Hessian Proxy工具允许你通过HTTP代理的方式交互Hessian服务,以便观察和分析传输的二进制数据。 总的来说,Hessian是一个值得学习的技术,尤其...
4. **源码分析** - 分析Hessian的源码可以帮助我们理解其内部实现,比如如何优化序列化过程,如何处理异常情况,以及如何实现类型兼容性等。这对于我们自定义序列化逻辑或优化现有应用的性能都非常有价值。 5. **...
读者可能能从中了解到如何集成Hessian到他们的项目中,以及如何通过源码分析来调试和优化Hessian服务。 从压缩包子文件的文件名称“BurlapWS”来看,这可能是与Burlap相关的,Burlap是Hessian的一个变种,也是一个...
3. **使用源码分析**: Hessian库提供了`HessianProxyFactoryBean`和`HessianServiceExporter`这两个关键类。前者用于客户端创建Hessian服务的代理,后者在服务端用于导出Hessian服务。通过阅读这些类的源码,我们...
此外,分析示例代码可以让我们了解如何在Java应用中集成Hessian,例如: - **服务发布**:如何使用Hessian的Server类来发布一个可远程调用的服务。 - **客户端调用**:客户端如何通过HessianProxyFactory来创建代理...
通过分析这些测试代码,我们可以更深入地了解Hessian的工作原理,以及如何在不同的场景下使用它。 总之,"自己写了个Hessian" 是一个关于实现Hessian协议的个人项目,涉及到对象序列化、HTTP通信、RPC服务等多个IT...
总的来说,Hessian 4.0.7与Spring 2.5.6的结合使用时出现的bug,可能涉及多个层面,需要综合运用源码阅读、调试技巧以及社区资源来定位和修复。在这个过程中,对Java、Spring和Hessian的深入理解,以及对问题排查的...
10. **源码分析**:通过阅读和理解提供的"src"文件,我们可以深入学习Flex客户端如何与Hessian服务通信的细节,以及可能遇到的问题和解决方案。 11. **HessianFlexClient.swf**:这个SWF文件可能是示例Flex客户端...
本次我们将深入探讨Hessian 4.0.7版本,包括其jar包的使用以及源码分析,帮助开发者更好地理解和应用这个强大的工具。 一、Hessian 4.0.7.jar——核心库 `hessian-4.0.7.jar`是Hessian的核心库文件,它包含了...
通过运行和分析`HessianDemo`,你可以更深入地理解Hessian的工作流程,包括如何创建服务端的Hessian服务,如何在客户端使用Hessian Proxy进行调用,以及如何处理返回结果。 总之,Hessian作为一种高效的RPC协议,...