Java二进制协议之Hessian实例(2)

本文深入介绍了Java中的Hessian二进制协议,包括序列化primitive type和reference type,以及Hessian的类型优化。通过实例展示了如何使用Hessian进行对象的序列化和反序列化,同时还探讨了Hessian的RPC功能,解释了如何编码调用信息和解码RPC信息来执行远程方法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

    前面的文章已经说了Hessian的一些基本信息,下面就通过一下基本实例由浅入深地看看Hessian的API如何使用。实例主要从两个方面进行介绍,首先我们需要看看Hessian的序列化功能,然后就是Hessian的RPC功能,因为RPC功能建立在序列化功能之上,因此我们看看序列化的功能;

  1. 序列化primitive type
    序列化primitive type虽然非常简单,但是我们需要了解Hessian的一些压缩功能,因为在序列化一个数据时需要记录两方法的信息:类型与数据,为了使得序列化的总数据尽量小,必须对常用的primitive type的类型进行压缩,因此Java的primitive type的类型都有缩写形式:
                            boolean:没有类型,直接写入T/F
            byte/short/integer:'I'
                                   long:'L'
                      float/double:'D'
    看实例代码:
        // 序列化primitive type
        ByteArrayOutputStream out = new ByteArrayOutputStream();
        Hessian2Output hOut = new Hessian2Output(out);
        hOut.writeInt(100);
        hOut.flush();
        byte[] bytes = out.toByteArray();  // 获取序列化的内容
        hOut.close();

        // 反序列化primitive type
        
    ByteArrayInputStream in = new ByteArrayInputStream(bytes);
        Hessian2Input hIn = new Hessian2Input(in);
        int i = hIn.readInt();
        hIn.close();
        
    Hessian的类型优化1:Hessian实际上对经常使用的类型进行了优化,例如Byte/Short/Integer类型也编码为:'I',Long类型编码为:'L',Float/Double类型编码为:'D',java.util.Date类型编码为:'d',String/Character/char/StringBuilder编码为:'S'
    Hessian的类型优化2:此优化仅仅对Hessian2有效,Hessian在序列化时不仅仅对写入的类型信息进行了优化,而且对类型的值(主要是正数和浮点数)也进行了优化;举个例子,我们写入一个200的long值,实际上我们只需要两个字节就可以存储而不是8个字节,同样对于float/double也可以节约非常多的空间,看下面的实例;
        Hessian2Output hOut = new Hessian2Output(out);
        hOut.writeInt(200);
        hOut.flush();
        byte[] bytes = out.toByteArray();    // 占用2个字节而不是4个字节!!
        hOut.close();
        ByteArrayInputStream in = new ByteArrayInputStream(bytes);
        Hessian2Input hIn = new Hessian2Input(in);
        int i = hIn.readInt();
        hIn.close();

  2. 序列化Reference Type
    Hessian序列化一个对象,使用的是“com.caucho.hessian.io.JavaSerializer”和“com.caucho.hessian.io.JavaDeserializer”类型进行序列化和反序列化,其原理非常简单,首先序列化时通过反射获取类型的所有Field(属性),然后依次写入所有属性的值,反序列化则相反;需要说明的是,对于对象的属性,如果是primitive type或者是常用类型,也会使用上面说的优化机制;
    备注:默认情况下Hessian也要求序列化的类型实现“java.io.Serializable”接口,不过可以通过配置对于为实现“”接口的类型也可以进行序列化
    简单实例:
    TestVO vo = new TestVO();
    vo.setI(1);
    vo.setiObj(2);
    vo.setJ(3L);
    vo.setjObj(4L);
    vo.setBigDec(BigDecimal.valueOf(5L));
    vo.setBigInt(BigInteger.valueOf(6L));
    vo.setStr("123");
    // 序列化Reference对象
    ByteArrayOutputStream out = new ByteArrayOutputStream();
    Hessian2Output hOut = new Hessian2Output(out);
    hOut.writeObject(vo);
    hOut.flush();
    byte[] bytes = out.toByteArray();
    hOut.close();
    // 反序列化Reference对象
    ByteArrayInputStream in = new ByteArrayInputStream(bytes);
    Hessian2Input hIn = new Hessian2Input(in);
    TestVO deVo = (TestVO) hIn.readObject();
    hIn.close();
  3. 序列化Array Type
    序列化Array实例与一般的Reference实例没有太大的区别,只不过是编码规则不一样而已,对于一个Array实例而言,首先写入的是数组元素(component)的类型,接着就是数字的长度,然后依次写入每个元素的值;
  4. 调用方法
    上面的实例仅仅使用了Hessian提供的序列化功能,实际上Hessian提供了RPC功能,即在序列化功能的基础上,提供了打包调用远程方法必须要的额外信息,例如调用方法的接口、方法名称等等,同时将所有参数序列化为字节,一起打包为二进制流通过socket发送到远程服务器;而在服务器端,则通过读取接口类型、方法名称以及所有的参数信息,同时反序列化所有的参数实例,就可以调用指定对象的方法,最后将返回值传递给客户端,完成RPC的调用;
    简单实例:
    // 需要调用的接口,在项目中客户端只需要接口信息
    public interface TestService {
    String getName(String custNo, int flag);
    }
    // 接口的简单实现,在项目中实现都位于服务器端,客户端只需要接口
    public class TestServiceImpl implements TestService {
    @Override
    public String getName(String custNo, int flag) {
    return "Test Name";
    }
    }
    // 编码调用信息
    ByteArrayOutputStream out = new ByteArrayOutputStream();
    Hessian2Output hOut = new Hessian2Output(out);
    hOut.call("getName", new Object[]{"0000000009", 1}); // 因为在项目中一个接口对应一个servlet,所以不需要发送接口类型信息
    hOut.flush();
    byte[] bytes = out.toByteArray();  // 在项目中,生成的字节会通过socket发送到服务器端
    hOut.close();

    // 解码RPC信息并调用函数
    ByteArrayInputStream in = new ByteArrayInputStream(bytes);
    Hessian2Input hIn = new Hessian2Input(in);
    HessianInputFactory _inputFactory = new HessianInputFactory();
    _inputFactory.readHeader(in);
    hIn.readCall();
    hIn.skipOptionalCall();
    String methodName = hIn.readMethod();  // 读取调用的方法名称
    int argLength = hIn.readMethodArgLength();  // 获取方法参数个数
    String custName = (String)hIn.readObject(String.class); // 按顺序读取参数值
    int flag = (Integer)hIn.readObject(int.class);
    // 通过反射获取方法并调用
    TestServiceImpl instance = new TestServiceImpl();
    Method method = TestService.class.getDeclaredMethod(methodName, String.class, int.class);
    Object result = method.invoke(instance, custName, flag);
  5. 其他
    在上面我们讲的RPC例子中,Hessian框架提供的功能要丰富并且更复杂,例如服务器端需要对Hessian的版本进行控制(有Hessian 1和Hessian 2两种),支持方法重载等等。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值