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

每天用心記錄一點點。內容也許不重要,但習慣很重要!


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM