MessagePack Java的使用

2016/11/16 17:33
阅读数 586

MessagePack是一个高效的二进制序列化格式。它让你像JSON一样可以在各种语言之间交换数据。但是它比JSON更快、更小。

使用Maven添加MessagePack的依赖:

<dependency>
<groupId>org.msgpack</groupId>
<artifactId>msgpack</artifactId>
<version>${msgpack.version}</version>
</dependency>

在本篇文章中使用的版本为

<msgpack.version>0.6.6</msgpack.version>

首先创建一个实体类UserInfo(注意对类加上Message注解)

import org.msgpack.annotation.Message;


@Message
public class UserInfo {


private String userName;
private int userID;

public String getUserName() {
return userName;
}
public void setUserName(String userName) {
this.userName = userName;
}
public int getUserID() {
return userID;
}
public void setUserID(int userID) {
this.userID = userID;
}

public UserInfo buildUserName(String userName){
this.userName = userName;
return this;
}

public UserInfo buildUserID(int userID){
this.userID = userID;
return this;
}

@Override
public String toString() {
return "UserInfo [userName=" + userName + ", userID=" + userID + "]";
}
}

看下如何进行序列化和反序列化

public class SerializablePerform {


public static void main(String[] args) throws Exception {
UserInfo userInfo = new UserInfo();
userInfo.buildUserID(250).buildUserName("saolangjian");
MessagePack messagePack = new MessagePack();
//序列化
byte[] bs = messagePack.write(userInfo);
System.out.println("byte array's length is : "+bs.length);
//反序列化
UserInfo serializableUserinfo = messagePack.read(bs, UserInfo.class);
System.out.println(serializableUserinfo);

}

}

如果想按顺序地序列化多个对象,可以使用Packer和Unpacker对象,这是因为每次的MessagePack.write(Object)和read(byte[])方法调用都会创建Packer和Unpacker对象,可以使用createPacker(OutputStream)和createUnpacker(InputStream)创建Packer对象和Unpacker对象

@Test
public void testMultiObjects() throws Exception {
UserInfo u1 = new UserInfo();
UserInfo u2 = new UserInfo();
UserInfo u3 = new UserInfo();
u1.buildUserID(250).buildUserName("saolangjian");
u2.buildUserID(25).buildUserName("shengun");
u3.buildUserID(13).buildUserName("chuichui");
MessagePack messagePack = new MessagePack();
//序列化
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
Packer packer = messagePack.createPacker(outputStream);
packer.write(u1);
packer.write(u2);
packer.write(u3);
byte[] bs = outputStream.toByteArray();
System.out.println("byte array's length is : "+bs.length);
//反序列化
ByteArrayInputStream inputStream = new ByteArrayInputStream(bs);
Unpacker unpacker = messagePack.createUnpacker(inputStream);
UserInfo su1 = unpacker.read(UserInfo.class);
System.out.println(su1);
UserInfo su2 = unpacker.read(UserInfo.class);
System.out.println(su2);
UserInfo su3 = unpacker.read(UserInfo.class);
System.out.println(su3);
}

Packer/Unpacker类允许序列化/反序列化多种类型的值,可以序列化/反序列化基本类型,基本类型的包装类,String对象,byte[]对象和ByteBuffer对象等。

@Test
public void testVariousType() throws Exception{
MessagePack messagePack = new MessagePack();

ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
Packer packer = messagePack.createPacker(outputStream);
//序列化基本类型
packer.write(true);
packer.write(10);
packer.write(10.1);
//序列化基本类型的包装类
packer.write(Boolean.TRUE);
packer.write(new Integer(10));
packer.write(new Double(10.1));
//序列化多种类型的数组
packer.write(new int[]{1,2,3,4});
packer.write(new Double[]{10.1,250.25});
packer.write(new String[]{"slj","cz","sg"});
packer.write(new byte[]{1,3,1});
//序列化其他引用类型
packer.write("saolangjian");
packer.write(ByteBuffer.wrap(new byte[]{1,3,1}));
packer.write(BigInteger.ONE);
byte[] bs = outputStream.toByteArray();

//反序列化
ByteArrayInputStream inputStream = new ByteArrayInputStream(bs);
Unpacker unpacker = messagePack.createUnpacker(inputStream);

boolean b = unpacker.readBoolean();
System.out.println(b);
int i = unpacker.readInt();
System.out.println(i);
double d = unpacker.readDouble();
System.out.println(d);
Boolean boolean1 = unpacker.read(Boolean.class);
System.out.println(boolean1);
Integer integer = unpacker.read(Integer.class);
System.out.println(integer);
Double double1 = unpacker.read(Double.class);
System.out.println(double1);
int[] js = unpacker.read(int[].class);
System.out.println(js.length);
Double[] doubles = unpacker.read(Double[].class);
System.out.println(doubles.length);
String[] strings = unpacker.read(String[].class);
System.out.println(strings.length);
byte[] cs = unpacker.read(byte[].class);
System.out.println(cs.length);
String text = unpacker.read(String.class);
System.out.println(text);
ByteBuffer buffer = unpacker.read(ByteBuffer.class);
byte[] newByte = new byte[buffer.remaining()];
System.out.println("remaining : "+buffer.remaining());
buffer.get(newByte);
System.out.println(new String(newByte));
BigInteger bigInteger = unpacker.read(BigInteger.class);
System.out.println(bigInteger);
}

可以使用Template来序列化容器比如List和Map,当序列化一个List对象,其中的元素是Integer类型时,创建Template的方法是:

Template<List<Integer>> integerTemplate = Templates.tList(Templates.TInteger);

其中tList是Templates的静态方法,TInteger是Templates的静态字段

@Test
public void testContainer () throws Exception{
MessagePack messagePack = new MessagePack();

Template<List<String>> listTemplate = Templates.tList(Templates.TString);
Template<Map<String, String>> mapTemplate = Templates.tMap(Templates.TString, Templates.TString);

ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
Packer packer = messagePack.createPacker(outputStream);
List<String> list = new ArrayList<String>();
list.add("saolangjian");
list.add("axiba");
list.add("woX");
packer.write(list);

Map<String, String> map = new HashMap<String,String>();
map.put("slj", "cz");
map.put("sg", "cc");
packer.write(map);

byte[] bs = outputStream.toByteArray();

ByteArrayInputStream inputStream = new ByteArrayInputStream(bs);
Unpacker unpacker = messagePack.createUnpacker(inputStream);
List<String> seList = unpacker.read(listTemplate);
System.out.println(seList);
Map<String, String> seMap = unpacker.read(mapTemplate);
System.out.println(seMap);
}

有些情况下,我们使用的实体类是外部类库中引用的,这时我们不能将@Message注解添加到类声明上,此时就有另一种方法进行操作,使用MessagePack.register方法

实体类的定义如下:

public class Account {

private double balance;
private String details;

public double getBalance() {
return balance;
}
public void setBalance(double balance) {
this.balance = balance;
}
public String getDetails() {
return details;
}
public void setDetails(String details) {
this.details = details;
}

@Override
public String toString() {
return "Account [balance=" + balance + ", details=" + details + "]";
}

}

序列化和反序列化的方法如下:

@Test
public void testRegister() throws Exception{
Account account = new Account();
account.setBalance(10.01);
account.setDetails("xxoo");
MessagePack messagePack = new MessagePack();
messagePack.register(Account.class);
byte[] bs = messagePack.write(account);
System.out.println(bs.length);
Account seAccount = messagePack.read(bs,Account.class);
System.out.println(seAccount);
}

为了保证序列化向前兼容,使用@Optional注解对新增加的字段,当反序列化旧版本的数据时,加入@Optional注解的字段就会被忽略

MessagePack提供了动态类型的功能,通过接口Value来实现动态类型,首先将字节数组序列化为Value类型的对象,然后用converter转化为本身的类型

@Test
public void testValue() throws Exception{
Account account = new Account();
account.setBalance(10.01);
account.setDetails("xxoo");
MessagePack messagePack = new MessagePack();
messagePack.register(Account.class);
byte[] bs = messagePack.write(account);
System.out.println(bs.length);
Value value = messagePack.read(bs);
Account seAccount = new Converter(messagePack,value).read(Account.class);
System.out.println(seAccount);
}

展开阅读全文
打赏
1
3 收藏
分享
加载中
更多评论
打赏
0 评论
3 收藏
1
分享
返回顶部
顶部