hessian原理

一.Hessian原理与协议简析:

    http的协议约定了数据传输的方式,hessian也无法改变太多:

    1) hessian中client与server的交互,基于http-post方式。

    2) hessian将辅助信息,封装在http header中,比如“授权token”等,我们可以基于http-header来封装关于“安全校验”“meta数据”等。hessian提供了简单的"校验"机制。

    3) 对于hessian的交互核心数据,比如“调用的方法”和参数列表信息,将通过post请求的body体直接发送,格式为字节流。

    4) 对于hessian的server端响应数据,将在response中通过字节流的方式直接输出。

 

    hessian的协议本身并不复杂,在此不再赘言;所谓协议(protocol)就是约束数据的格式,client按照协议将请求信息序列化成字节序列发送给server端,server端根据协议,将数据反序列化成“对象”,然后执行指定的方法,并将方法的返回值再次按照协议序列化成字节流,响应给client,client按照协议将字节流反序列话成"对象"。

Client端:

    在Client端,核心API为:

    1) HessianProxyFactory: 负责托管"远程接口"和"远程hessian服务的URL",并生成代理类(Java Proxy实例)。

    2) HessianProxy: Proxy实例的驱动器(handler),当代理实例的方法调用时,HessianProxy负责序列化"方法名"/"参数列表"等,并调用远程URL获取响应数据;同时也负责反序列化。底层使用HttpURLConnection。

    3) HessianOutput: 负责将序列化的字节数据,按照协议,写入inputStream,并通过URL Connection发送给远端。

 

    hessian-client发送请求的首要条件,就是需要指明url,此url就是server端暴露的servlet地址。

HessianProxyFactory proxyFactory = new HessianProxyFactory();  
HelloService service = (HelloService)proxyFactory.create(HelloService.class, "http://localhost:8080/hessian/helloService");  
System.out.println(service.sayHello("hessian"));  

     上述代码样例中,HelloService表示远程接口API,其中URL中“helloService”表示调用的“服务名称”,这个“服务名称”有server端决定,所以Client需要首先知道所需服务的URL全路径。那么方法的调用数据,将会按照如下“序列”发送(俗称“字节码成帧”):

[“方法名称“的字节长度]["方法名称”字节序列][参数的个数]{[参数类型][”参数“的字节长度][”参数“的字节序列]...}  
[8][sayHello][1]['S'][5]['hello']  
//其中“8”表示“sayHello”方法名称为8个字节  
//"1"表示参数的个数为1  
//“S”表示参数的类型为“String”,hessian中定义了大量的简写字母,用来表示java数据类型  
//“5”表示参数的字节个数为5  
//"hello"表示此参数的值为“hello”,不过实际上传输的应该是“hello”对应的字节序列。

 如果你从事过socket通信方面的开发,你应该知道server端会如何“解析”这个字节流信息;对于Hessian-server端而言,也是根据“字节码成帧”,逐个读取信息,比如首先读取一个32位的int,得到“8”,然后读取8个字节并使用utf8的方式编码成String字符串,将获得“sayHello”,此时server端已经可以知道client需要调用的方法名称为“sayHello”;然后对于一个32为的int,得到1,表示参数列表的个数为1;然后在读取一个字节,获得“S”,表示参数为String类型.....

 

    Server端执行结束后,Http响应的字节流格式基本和上述类似。那么HessianProxy负责反序列化和类型转换即可。

 

    需要注意,Hessian Client默认不支持“重载”方法的调用,通常我们需要开启“OverloadEnabled”属性设置为true。此后在方法调用时,Hessian将会把“方法签名” + “_” + “参数类型”作为新的方法名称发送给Server端。 

proxyFactory.setOverloadEnabled(true);//默认为false  

Server端:

    在Server端最重要的类,就是HessianServlet;它是一个普通的Java Servlet实现,每个“服务”都需要配置一个HessianServlet实例,它负责接收Client发送的Http请求,请求类型必须是POST。

 

<servlet>  
    <servlet-name>helloService</servlet-name>  
    <servlet-class>com.caucho.hessian.server.HessianServlet</servlet-class>  
    <init-param>  
        <param-name>service-class</param-name>  
        <param-value>com.test.hessian.impl.HelloServiceImpl</param-value>  
    </init-param>  
</servlet>  
  
<servlet-mapping>  
    <servlet-name>helloService</servlet-name>  
    <url-pattern>/hessian/helloService</url-pattern>  
</servlet-mapping>

    从上述实例中,我们看出HessianServlet需要一个重要的初始化参数“service-class”,它的值必须是一个良好的“远程接口”实现类(默认构造器)。HessianSkeleton和Client端的HessianProxy对应,它是负责server端Http请求的核心类,每个HessianServlet都会持有一个HessianSkeleton实例,这个实例持有“service-class”对象,并在初始化时通过反射机制将“service-class”的所有方法列表放在一个methodMap中,key为“方法名”,value为Method(java.lang.reflect.Method),同时为了避免方法重载,还会额外的将“方法名_参数类型”作为一个新key,也放入methodMap中。

 

    在HessianServlet初始化时,会通过反射机制的方式创建一个“service-class”的实例,当Http请求到达Servlet时,HessianSkeleton实例负责从请求中解析出“方法名”和参数列表;那么到此为止,一切就很清楚了,HessianSkeleton根据方法名,从methodMap中获取Method,并调用其invode方法;然后将执行结果反序列化,写入Response。

hessian主要特性

    1) Hessian的client每次调用,都会开启一个新的http链接,所以各个调用之间无法共享数据,其实你可以使用cookie技术来保存相关数据,但是事实上收效甚微。

    2) Hessian的client使用了java的动态代理,因为client需要明确知道接口的API信息。

    3) Hessian的接口API中,无论是方法的参数还是方法的返回值,都必须是可序列化的(实现Serializable接口),你可以通过重写Serializable接口的相关方法,来自定义序列化/反序列化操作。

    4) 不要尝试使用hessian交互大数据。

    5) 不要尝试对hessian的交互数据的二进制流进行额外的加密,这是一件得不偿失的事情,虽然看起来安全,事实上收效甚微。

三.核心API:

    1) HessianProxy

    2) HessianProxyFactory

    3) HessianInput:输入流控制,用来反序列化响应的结果,其中包括remote端的异常栈(在client端将会被重新抛出),“Fault”信息(remote端的失败信息,比如格式错误等);很多时候,你可以通过指定http response-code值来实现特定的请求失败信号。

    4) HessianOutput:输出流控制,用来序列化请求的数据

    5) Deserializer:反序列化接口,大量的实现类用于反序列化不同类型的数据

    6) Serializer:序列化接口

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值