msgpack-java第一课

msgpack-java

It’s like JSON. but fast and small.

本文回答一下几个问题:
- 在Java中, msgpack如何实现打包,解包
- 在Java中,如何方便地实现对List, Map数据结构的序列化
- 在Java中,如果通讯双方类对象版本不统一,解包会有问题吗?

在Java中, msgpack如何实现打包,解包

java中打包,解包相当的容易。
引用msgpack包,包中有一个org.msgpack.annotation.Message的注解,带该注解的类即可实现打包和解包(序列化和反序列化)。

public class App 
{
    public static void main( String[] args )
    {
        MessagePack packer = new MessagePack();
        A a = new A();
        a.setiVal(10);
        a.setsVal("Hello");

        try {
            byte[] adata = packer.write(a); // 打包(序列化)
            A a2 = packer.read(adata , A.class); // 解包(反序列化)
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}
// 带注解的类
@Message
class A{
    private Integer iVal;
    private String sVal;
    public Integer getiVal() {
        return iVal;
    }
    public void setiVal(Integer iVal) {
        this.iVal = iVal;
    }
    public String getsVal() {
        return sVal;
    }
    public void setsVal(String sVal) {
        this.sVal = sVal;
    }
}

在Java中,如何方便地实现对List, Map数据结构的序列化

如果需要简单的原生对象的List对象,可以使用Templates下面的方法,不过最简单的方式是把List, Map对象做为属性添加到具有Message注解的类中。例如:

@Message
class LA{
    private List<A> as;

    public List<A> getAs() {
        return as;
    }

    public void setAs(List<A> as) {
        this.as = as;
    }
}

上面这个LA类就可以轻松实现List对象的序列化和反序列化,和普通类对象一样使用。

在Java中,如果通讯双方类对象版本不统一,解包会有问题吗?

这个问题,一般开始不会遇到。
众所周知,像XML, JSON这样的结构化数据有一个非常大的优点就是结构的稳定性非常好,对结构的修改不会引起老版本的问题。他们结构化的数据都是基于标签访问的,而msgpack是基于数据的。如果如前面的方法实现序列化,那么序列化/反序列化是基于数据的位置进行的,如果后期数据变更,很可能,数据就会存在问题。
经过测试,发现一下规律:
1. 如果两个类变量的顺序相同,其中一个类增加了变量,多了变量的类序列化出来的数据可以放序列化到变量少的类,反之也是可以的,但必需要求所有变量都是包装类变量(是Integer, 不是int),不然就报错。
2. 数组的数据不受此影响,数组元素必需适用规律1
3. Map是类似于JSON的数据存储方式,兼容性好,相当于把变量名称进行传输。
请看示例:

public class App 
{
    public static void main( String[] args )
    {
        MessagePack packer = new MessagePack();
        A a = new A();
        a.setiVal(10);
        a.setsVal("Hello");
        B b = new B();
        b.setiVal(10);
        b.setsVal("Hello");
        b.setOk(true);
        C c = new C();
        c.setiVal(10);
        c.setsVal("Hello");

        LB lb = new LB();
        List<B> as = new ArrayList<B>();
        as.add(b);
        B b1 = new B();
        b1.setiVal(22);
        b1.setsVal("Hellox");
        b1.setOk(true);
        as.add(b1);
        lb.setAs(as);

        MA ma = new MA();
        HashMap<String, A> mamap = new HashMap<String, A>();
        mamap.put("A", a);
        mamap.put("B", a);
        ma.setMap(mamap);

        try {
            byte[] adata = packer.write(a);
            byte[] bdata = packer.write(b);
            byte[] cdata = packer.write(c);
            byte[] lbdata = packer.write(lb);
            byte[] madata = packer.write(ma);
            A a2 = packer.read(bdata, A.class); // 用类B的数据,反序列化A对象也是可以的
//          A a3 = packer.read(cdata, A.class); // ERROR, C的数据编码格式和A的前半部分不同
            LA la2 = packer.read(lbdata, LA.class); // 用类B 的List数据,可以反序列化LA的实例
            MA ma2 = packer.read(madata, MA.class); // Map的适用性好
            B b2 = packer.read(adata, B.class); // 如果变量都是类变量,A类的数据也可以放序列化
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }
}

@Message
class A{
    private Integer iVal;;
    private String sVal;
    public Integer getiVal() {
        return iVal;
    }
    public void setiVal(Integer iVal) {
        this.iVal = iVal;
    }
    public String getsVal() {
        return sVal;
    }
    public void setsVal(String sVal) {
        this.sVal = sVal;
    }
}

@Message
class LA{
    private List<A> as;

    public List<A> getAs() {
        return as;
    }

    public void setAs(List<A> as) {
        this.as = as;
    }
}

@Message
class MA{
    private HashMap<String, A> map;

    public HashMap<String, A> getMap() {
        return map;
    }

    public void setMap(HashMap<String, A> map) {
        this.map = map;
    }
}

@Message
class B{
    private Integer iVal;
    private String sVal;
    private Boolean isOk;

    public Integer getiVal() {
        return iVal;
    }
    public void setiVal(Integer iVal) {
        this.iVal = iVal;
    }
    public String getsVal() {
        return sVal;
    }
    public void setsVal(String sVal) {
        this.sVal = sVal;
    }
    public Boolean isOk() {
        return isOk;
    }
    public void setOk(Boolean isOk) {
        this.isOk = isOk;
    }
}

考虑兼容性,作为交互的数据类必需符合如下规则:
1. 类成员全部采用包装类
2. 一定定义好类,不能删除,修改,前中部插入类成员,只允许扩容
3. 对于数据变化较大的情况,考虑适用Map的方式更灵活。

在回答问题后,简要说明一下msgpack可以使用的场合。msgpack实现了多语言统一的序列化标准,从而可以实现在不同语言中实现结构化数据的交换。更为重要的是,msgpack有很多种语言的版本,这样跨语言的通讯就有了极大的优势。ActiveMQ通过JMS实现消息的序列化,JMS实质上也是一个标准话的数据结构。JSON也是标准话的结构,在JS王国中经常用到。阿里云的RocketMQ消息队列开源,并进入Apache孵化项目,它的消息内容是字节流,这意味着需要自己定义消息的格式。通过msgpack就可以方便的实现数据的交换。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
/home/AQTJClient/AQTJAuditClient/depends/msgpack-c-master/include/msgpack/v1/object.hpp:664:34: error: ‘void* memcpy(void*, const void*, size_t)’ copying an object of non-trivial type ‘struct msgpack::v2::object’ from an array of ‘const msgpack_object’ {aka ‘const struct msgpack_object’} [-Werror=class-memaccess] std::memcpy(&o, &v, sizeof(v)); ^ In file included from /home/AQTJClient/AQTJAuditClient/depends/msgpack-c-master/include/msgpack/object_fwd.hpp:17, from /home/AQTJClient/AQTJAuditClient/depends/msgpack-c-master/include/msgpack/v1/adaptor/adaptor_base_decl.hpp:14, from /home/AQTJClient/AQTJAuditClient/depends/msgpack-c-master/include/msgpack/adaptor/adaptor_base_decl.hpp:13, from /home/AQTJClient/AQTJAuditClient/depends/msgpack-c-master/include/msgpack/adaptor/adaptor_base.hpp:13, from /home/AQTJClient/AQTJAuditClient/depends/msgpack-c-master/include/msgpack/v1/object_decl.hpp:16, from /home/AQTJClient/AQTJAuditClient/depends/msgpack-c-master/include/msgpack/object_decl.hpp:14, from /home/AQTJClient/AQTJAuditClient/depends/msgpack-c-master/include/msgpack/object.hpp:13, from /home/AQTJClient/AQTJAuditClient/depends/msgpack-c-master/include/msgpack.hpp:10, from /home/AQTJClient/AQTJAuditClient/depends/msgpack-c-master/example/cpp03/stream.cpp:10: /home/AQTJClient/AQTJAuditClient/depends/msgpack-c-master/include/msgpack/v2/object_fwd.hpp:23:8: note: ‘struct msgpack::v2::object’ declared here struct object : v1::object { ^~~~~~ cc1plus: all warnings being treated as errors make[2]: *** [example/cpp03/CMakeFiles/stream.dir/build.make:63:example/cpp03/CMakeFiles/stream.dir/stream.cpp.o] 错误 1 make[2]: 离开目录“/home/AQTJClient/AQTJAuditClient/depends/msgpack-c-master” make[1]: *** [CMakeFiles/Makefile2:415:example/cpp03/CMakeFiles/stream.dir/all] 错误 2 make[1]: 离开目录“/home/AQTJClient/AQTJAuditClient/depends/msgpack-c-master”
07-20
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值