Hessian是一个轻量级的二进制远程调用框架,官方文档地址,它主要包括Hessian远程调用协议、Hessian序列化协议以及客户端服务端代理等几部分,关于Hessian协议可以看下另外一篇文章Hessian远程调用及序列化协议。Hessian远程调用框架构建在Http协议之上,下面是示意图。

下面这个图是一次远程调用的过程

其中步骤3、4、5、6是核心过程,还要细化下,

步骤3:将远程方法调用转换为hessian调用,具体为,客户端首先要先和服务器端建立Socket连接,然后发送Http请求,hessian远程调用及经过Hessian序列化的参数等二进制数据作为http请求的数据部分被提交到服务端,并且目前只支持Post提交方法。

步骤4:将hessian调用转换为本地方法调用,步骤3里请求的url是暴露服务时映射好的,也即指定的服务端代理对象会解析客户端服务代理对象进行的hessian远程调用,然后反序列化参数,找到被代理的服务类(暴露服务时指定的服务类),通过反射调用服务类中的相应服务方法。

步骤5:返回远程调用返回值给服务调用者,步骤4里调用服务类的方法会返回具体值,经过Hessian序列化后作为hessian调用的返回值,被放在http响应的body部分被返回给客户端。

步骤6:客户端代理对象解析body部分hessian调用返回reply,解析出远程调用返回值再反序列化,最终得到结果。

再此举例说明:

先看一下demo中涉及到的对象,其中灰色部分Proxy$N、HessianSkeleton分别对应第一张图里面的客户端远程代理对象和服务端代理对象。深绿色部分HessianProxy是创建动态代理时所需的InvocationHandler,HessianProxy和HessianSkeleton是hessian框架的核心类。一般都是在客户端通过HessianProxyFactory创建一个动态代理,将远程方法调用转为http请求携带hessian调用数据,并接受相应的返回值。HessianSkeleteton代理具体的服务类比如HessianImpl,最终一个远程方法调用都会转换为对HessianImpl中的本地方法调用。

1.实体类TradeItemDto

  1. package hessian;
  2. import java.math.BigDecimal;
  3. public class TradeItemDto implements java.io.Serializable {
  4. private static final long serialVersionUID = -1074152706947019647L;
  5. private BigDecimal amount;
  6. public BigDecimal getAmount(){
  7. return amount;
  8. }
  9. public void setAmount(java.math.BigDecimal amount) {
  10. this.amount = amount;
  11. }
  12. public String toString() {
  13. return this.amount.toString();
  14. }
  15. }

2.远程服务接口类

  1. package hessian;
  2. public interface IHessian {
  3. public String say(TradeItemDto tradeItemDto);
  4. }

3.远程接口服务实现类

  1. package hessian;
  2. import com.caucho.hessian.server.HessianServlet;
  3. public class HessianImpl extends HessianServlet implements IHessian{
  4. public String say(TradeItemDto tradeItemDto) {
  5. return "Hello " + tradeItemDto.toString();
  6. }
  7. }

4.通过servlet暴露远程服务

  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <web-app xmlns="http://java.sun.com/xml/ns/j2ee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  3. version="2.4"
  4. xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee   http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">
  5. <servlet>
  6. <servlet-name>ihessian</servlet-name>
  7. <servlet-class>hessian.HessianImpl</servlet-class>
  8. <init-param>
  9. <param-name>debug</param-name>
  10. <param-value>true</param-value>
  11. </init-param>
  12. </servlet>
  13. <servlet-mapping>
  14. <servlet-name>ihessian</servlet-name>
  15. <url-pattern>/test</url-pattern>
  16. </servlet-mapping>
  17. </web-app>

5.客户端远程服务调用类

  1. package hessian;
  2. import java.net.MalformedURLException;
  3. import com.caucho.hessian.client.HessianProxyFactory;
  4. public class TestHessian {
  5. public static void main(String[] args) {
  6. String url = "http://localhost:8080/hessian/test";
  7. HessianProxyFactory factory = new HessianProxyFactory();
  8. IHessian h = null;
  9. try {
  10. h = (IHessian) factory.create(IHessian.class, url);
  11. } catch (MalformedURLException e) {
  12. System.out.println("occur exception: " + e);
  13. }
  14. TradeItemDto tradeItemDto = new TradeItemDto();
  15. tradeItemDto.setAmount(new java.math.BigDecimal(2999));
  16. System.out.println(h.say(tradeItemDto));
  17. }
  18. }

客户端结果及服务端Debug输出

Hello 2999

下面是Debug输出,打印了hessian调用过程,我们说Hessian是二进制协议,它输出到流里面的都是二进制协议内容或者数据内容,区别于文本协议及文本数据内容。下面是hessian协议及hessian序列化的可视化,是为了帮助我们理解hessian调用过程。

  1. 17:48:38,169 ERROR [STDERR] 2010-9-25 17:48:38 com.caucho.hessian.server.HessianSkeleton$LogWriter write
  2. 良好: call 2.0
  3. 17:48:38,170 ERROR [STDERR] 2010-9-25 17:48:38 com.caucho.hessian.server.HessianSkeleton$LogWriter write
  4. 良好:   method "say"
  5. 17:48:38,170 ERROR [STDERR] 2010-9-25 17:48:38 com.caucho.hessian.server.HessianSkeleton$LogWriter write
  6. 良好:   map hessian.TradeItemDto (#0)
  7. 17:48:38,171 ERROR [STDERR] 2010-9-25 17:48:38 com.caucho.hessian.server.HessianSkeleton$LogWriter write
  8. 良好:     "amount" => map java.math.BigDecimal (#1)
  9. 17:48:38,171 ERROR [STDERR] 2010-9-25 17:48:38 com.caucho.hessian.server.HessianSkeleton$LogWriter write
  10. 良好:                   "scale" => 0
  11. 17:48:38,171 ERROR [STDERR] 2010-9-25 17:48:38 com.caucho.hessian.server.HessianSkeleton$LogWriter write
  12. 良好:                   "intVal" => null
  13. 17:48:38,172 ERROR [STDERR] 2010-9-25 17:48:38 com.caucho.hessian.server.HessianSkeleton$LogWriter write
  14. 良好: Hessian 2.0
  15. 17:48:38,172 ERROR [STDERR] 2010-9-25 17:48:38 com.caucho.hessian.server.HessianSkeleton$LogWriter write
  16. 良好: Reply
  17. 17:48:38,173 ERROR [STDERR] 2010-9-25 17:48:38 com.caucho.hessian.server.HessianSkeleton$LogWriter write
  18. 良好:   "Hello 2999"

备注:

1)3.13 以上版本支持debug,可以输出协议内容及序列化流

2)可以打开或者关闭远程调用方法是否可重载标志,方法参数个数必须固定,不支持变长参数

3) 注意客户端与服务端使用hessian.jar包版本

4)spring集成hessian

5)hessian调用原理决定客户端与服务端使用的接口类全限定名不必相同,只需方法名字参数要相同。

Hessian轻量级二进制远程调用框架的更多相关文章

  1. ZooKeeper伪分布集群安装及使用 RMI+ZooKeeper实现远程调用框架

    使用 RMI + ZooKeeper 实现远程调用框架,包括ZooKeeper伪集群安装和代码实现两部分.  一.ZooKeeper伪集群安装: 1>获取ZooKeeper安装包 下载地址:ht ...

  2. ZeroC ICE的远程调用框架 Slice如何帮助我们进行Ice异步编程(AMI,AMD)

    Slice最大的用处就是为我们使用Ice进行编程,代劳绝大部分的重复性代码,并提供一些帮助性的框架代码,如用于AMI和AMD方式进行异步编程的回调框架. 当Slice不为我们生成代码时,我们仍然可以按 ...

  3. ZeroC ICE的远程调用框架 AMD

    继上一篇<ZeroC ICE的远程调用框架>,本篇再来说其中的AMD.(本篇需要重写) 当在ice文件中声明某个接口方法Method为["amd"]后,接口方法在stu ...

  4. ZeroC ICE的远程调用框架

    想搞清楚slice为我们生成了什么样的框架代码,就先搞明白Ice的远程调用框架暗中为我们做了些什么? Ice将Ice Object的方法调用分为三个阶段(或步骤),分别是begin,process和e ...

  5. Hessian怎样实现远程调用

    1.Spring中除了提供HTTP调用器方式的远程调用,还对第三方的远程调用实现提供了支持,其中提供了对Hessian的支持. Hessian是由Caocho公司发布的一个轻量级的二进制协议远程调用实 ...

  6. alibaba远程调用框架dubbo原理

    alibaba有好几个分布式框架,主要有:进行远程调用(类似于RMI的这种远程调用)的(dubbo.hsf),jms消息服务(napoli.notify),KV数据库(tair)等.这个框架/工具/产 ...

  7. 使用 RMI + ZooKeeper 实现远程调用框架

    目录[-] 1 发布 RMI 服务1.1 定义一个 RMI 接口1.2 编写 RMI 接口的实现类1.3 通过 JNDI 发布 RMI 服务2 调用 RMI 服务3 RMI 服务的局限性4 使用 Zo ...

  8. [转载] 基于Dubbo的Hessian协议实现远程调用

    转载自http://shiyanjun.cn/archives/349.html Dubbo基于Hessian实现了自己Hessian协议,可以直接通过配置的Dubbo内置的其他协议,在服务消费方进行 ...

  9. 基于Dubbo的Hessian协议实现远程调用

    Dubbo基于Hessian实现了自己Hessian协议,可以直接通过配置的Dubbo内置的其他协议,在服务消费方进行远程调用,也就是说,服务调用方需要使用Java语言来基于Dubbo调用提供方服务, ...

随机推荐

  1. 工控安全入门(二)—— S7comm协议

    在上一次的文章中我们介绍了施耐德公司的协议modbus,这次我们把目标转向私有协议,来看看另一家巨头西门子的S7comm.首先要说明,这篇文章中的内容有笔者自己的探索,有大佬们的成果,但由于S7com ...

  2. 2016中国人工智能企业TOP100, CBinsight2016年100家人工智能公司

    2016中国人工智能企业TOP100 不论在学界还是业界,均有代表人物对人工智能表示了担忧,如史蒂芬·霍金和比尔·盖茨.尽管如此,国内外科技巨头都积极发力人工智能,一波波创业者也相继涌入.人工智能成为 ...

  3. 请问“javascript:;”是什么意思?

    请问“javascript:;”是什么意思?   最佳答案   就是 执行一段 空白JAVASCRIPT语句 并且返回的也是空或者false值..把 javascript:; 加在超级链接上 就可以防 ...

  4. 使用Httpclient 完美解决服务端跨域问题

    项目需求: jsonp是从前台js的角度考虑,通过Ajax调用springMVC的接口.同一个ip.同一个网络协议.同一个端口,三者都满足就是同一个域,否则就是跨域问题了.首页广告需要一个轮播的效果, ...

  5. 洛谷P2381 圆圆舞蹈

    P2381 圆圆舞蹈 题目描述 熊大妈的乃修在时针的带领下,围成了一个圆圈舞蹈,由于没有严格的教育,奶牛们之间的间隔不一致. 奶牛想知道两只最远的奶牛到底隔了多远.奶牛A到B的距离为A顺时针走和逆时针 ...

  6. 手把手教你如何玩转消息中间件(ActiveMQ) https://blog.csdn.net/cs_hnu_scw/article/details/81040834

    #情景引入小白:起床起床起床起床....快起床~我:怎么了又,大惊小怪,吓到我了.小白:我有事有事想找你,十万火急呢~~我:你能有什么事?反正我不信..那你说说看~~小白:就是我有两个小表弟,叫大白和 ...

  7. Java static 关键字学习

    static:意为静态的,简单理解就是公共的.独立于实例变量之外的1.概述:static是Java中常用的关键字,一般用于变量.方法.静态代码块.内部类上.静态导包2.用法: a.用于变量上表示该变量 ...

  8. FreeMarker中<#include>和<#import>标签的区别

    在使用freemarker作为前端页面模板的应用中,会有很多的freemarker模板页面,这些ftl会在不同的页面中重复使用,一是为了简化布局的管理,二是可以重复使用一些代码. 在freemarke ...

  9. php array_key_exists() 与 isset() 的区别

    一个基本的区别是isset()可用于数组和变量,而array_key_exits()只能用于数组. 但是最主要的区别在于在设定的条件下的返回值. 现在我们来验证一下这个最主要的区别. array_ke ...

  10. The World's Top 15 Stock Exchanges by Domestic Market Capitalization

     The World's Top 15 Stock Exchanges by Domestic Market Capitalization in 2008 4 Euronext Belgium, Fr ...