MessagePack 使用

MessagePack 使用

MessagePack(https://msgpack.org/) 是一个基于二进制高效的对象序列化 Library 用于跨语言通信。它可以像 JSON 那样,在许多种语言之间交换结构对象;但是它比 JSON 更快速也更轻巧。 支持 Python、Ruby、Java、C/C++、Javascript 等众多语言。 比 Google Protocol Buffers 还要快 4 倍。

MessagePack 特点:编解码高效,性能高;序列化之后的码流小。

快速入门:https://github.com/msgpack/msgpack-java

一、环境准备

<dependency>
    <groupId>org.msgpack</groupId>
    <artifactId>msgpack</artifactId>
    <version>0.6.12</version>
</dependency>

二、MessagePack 使用

/**
 * 关于Msgpack官网上是这么说的,It's like JSON.but fast and small
 * 1.单个对象使用 Msgpack <BR />
 *   1.1 此对象必须要实现 Serializable 接口(java.io.Serializable) <BR />
 *   1.2 此对象必须要使用 @Message 注解(org.msgpack.annotation.Message) <BR />
 *   1.3 此对象属性中不能有用 transient 修饰的字段. <BR />
 * 2.序列化List,Map(List接口)直接这么做msgpack不支持.
 * @author: leigang
 * @version: 2018-04-28
 */
public class MsgpackTest {

    private long time;
    private MessagePack msgpack;

    private UserBean user = new UserBean("binarylei", 22, true, 2000.0);

    @Before
    public void beforeTest() {
        time = System.currentTimeMillis();
        msgpack = new MessagePack();
        //msgpack.register(UserBean.class);
    }

    @After
    public void afterTest() {
        msgpack.unregister();
        System.out.println(System.currentTimeMillis() - time);
    }

    //1. MessagePack 入门
    @Test
    public void test() throws IOException {
        List<String> src = Arrays.asList(new String[]{"java", "python", "c"});

        // Serialize
        byte[] raw = msgpack.write(src);

        // Deserialize directly using a template
        List<String> dst1 = msgpack.read(raw, Templates.tList(Templates.TString));
        System.out.println(dst1);

        // Or, Deserialze to Value then convert type.
        Value dynamic = msgpack.read(raw);
        List<String> dst2 = new Converter(dynamic).read(Templates.tList(Templates.TString));
        System.out.println(dst2);
    }

    //2. JavaBean 对象序列化
    @Test
    public void testObject() throws IOException {
        byte[] bytes = msgpack.write(user);
        UserBean newValue = msgpack.read(bytes, UserBean.class);
        Assert.assertEquals(user.getName(), newValue.getName());
    }

    //3. JavaBean 包含 List,Map 属性,使用方式同上
    @Test
    public void testBean() throws IOException {
        ListUserBean src = new ListUserBean();
        List<UserBean> lst = new ArrayList<>();
        lst.add(user);
        src.setList(lst);

        byte[] bytes = msgpack.write(src);
        ListUserBean dst1 = msgpack.read(bytes, ListUserBean.class);
        System.out.println(dst1.getList());
    }

    //4. List
    @Test
    public void testList() throws IOException {
        List<UserBean> lst = new ArrayList<UserBean>();
        for (int i = 0; i < 10; i++) {
            lst.add(user);
        }

        byte[] bytes = msgpack.write(lst);
        List<UserBean> newValue = msgpack.read(bytes, Templates.tList(msgpack.lookup(UserBean.class)));
        Assert.assertEquals(lst.size(), newValue.size());
    }

    //5. Set
    @Test
    public void testSet() throws IOException {
        Set<UserBean> set = new HashSet<UserBean>();
        for (int i = 0; i < 10; i++) {
            set.add(user);
        }

        byte[] bytes = msgpack.write(set);
        Set<UserBean> newValue = msgpack.read(bytes, Templates.tSet(msgpack.lookup(UserBean.class)));
        Assert.assertEquals(set.size(), newValue.size());
    }

    //6. Map
    @Test
    public void testMap() throws IOException {
        Map<String, UserBean> map = new HashMap<>();
        for (int i = 0; i < 10; i++) {
            map.put(String.valueOf(i), user);
        }

        byte[] bytes = msgpack.write(map);
        Map<String, UserBean> newValue = msgpack.read(bytes,
                Templates.tMap(Templates.TString, msgpack.lookup(UserBean.class)));
        Assert.assertEquals(map.size(), newValue.size());
    }
}

测试用的 bean 对象如下:

@Message
public class UserBean implements Serializable {

    private String name;
    private int age;
    private boolean sex;
    private double salary;

    // 省略 getter/setter/constructor ...
}

@Message
public class ListUserBean {
    public List<UserBean> list;

    public List<UserBean> getList() {
        return list;
    }

    public void setList(List<UserBean> list) {
        this.list = list;
    }
}

三、踩过的坑

(1) 问题:Object 无法序列化

问题详见:https://github.com/msgpack/msgpack-java/issues/4

org.msgpack.MessageTypeException: Cannot find template for class java.lang.Object class. Try to add @message annotation to the class or call MessagePack.register(Type).
    at org.msgpack.template.TemplateRegistry.lookup(TemplateRegistry.java:220)
    at org.msgpack.template.TemplateRegistry.lookupGenericTypeImpl(TemplateRegistry.java:258)
    at org.msgpack.template.TemplateRegistry.lookupGenericType(TemplateRegistry.java:230)
    at org.msgpack.template.TemplateRegistry.lookup(TemplateRegistry.java:180)

如下 Map<String, Object> 中的 Object 出错,解决方法就是用具体的类代替 Object

@Message
public class Header implements Serializable {
    // ...
    //private Map<String, Object> attachmet = new HashMap<>();
    private Map<String, String> attachmet = new HashMap<>();
}

参考:

  1. https://msgpack.org/
  2. https://github.com/msgpack/msgpack-java

每天用心记录一点点。内容也许不重要,但习惯很重要!

原文地址:https://www.cnblogs.com/binarylei/p/8978485.html