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<>();
}
参考:
每天用心记录一点点。内容也许不重要,但习惯很重要!