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;
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对象
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对象等。
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的静态字段
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); }