使用Protostuff實現序列化與反序列化
(1)Protobuf介紹
Google Protocol Buffer( 簡稱 Protobuf) 是 Google 公司內部的混合語言數據標準,目前已經正在使用的有超過 48,162 種報文格式定義和超過 12,183 個 .proto 文件。他們用於 RPC 系統和持續數據存儲系統。
Protocol Buffers 是一種輕便高效的結構化數據存儲格式,可以用於結構化數據串行化,或者說序列化。它很適合做數據存儲或 RPC 數據交換格式。可用於通訊協議、數據存儲等領域的語言無關、平臺無關、可擴展的序列化結構數據格式。目前提供了 C++、Java、Python 三種語言的 API。
(2)Protobuf優點
平臺無關,語言無關,可擴展;
提供了友好的動態庫,使用簡單;
解析速度快,比對應的XML快約20-100倍;
序列化數據非常簡潔、緊湊,與XML相比,其序列化之後的數據量約爲1/3到1/10;
獨立於語言,獨立於平臺,最最重要的是它的效率相當高,用protobuf序列化後的大小是json的10分之一,xml格式的20分之一,是二進制序列化的10分之一,
(3)Protobuf主要流程
需要自己寫一個.proto文件用來描述序列化的格式,然後用Protobuf提供的protoc工具將.proto文件編譯成一個Java文件,最後將該Java文件引入到項目中就可以了。
(4)Protostuff介紹
google原生的protobuffer使用起來相當麻煩,首先要寫.proto文件,然後編譯.proto文件,生成對應的.java文件。protostuff基於Google Protobuf,好處就是不用自己寫.proto文件同時在幾乎不損耗性能的情況下即可實現對象的序列化與反序列化。
(5)使用Protostuff示例
Protostuff版本:
使用Protostuff實現Jedis中Club對象的讀取:
代碼結構爲:
序列化工具類ProtostuffSerializer 提供了序列化和反序列化方法:
// 序列化工具
public byte[] seriable(final Club club) {
final LinkedBuffer linkedBuffer = LinkedBuffer.allocate(LinkedBuffer.DEFAULT_BUFFER_SIZE);
try {
return serializeInternal(club, schema, linkedBuffer);
} catch (final Exception e) {
throw new IllegalStateException(e.getMessage(), e);
} finally {
linkedBuffer.clear();
}
}
// 實際序列化工具
private <T> byte[] serializeInternal(final T source, final Schema<T> schema, final LinkedBuffer linkedBuffer) {
return ProtostuffIOUtil.toByteArray(source, schema, linkedBuffer);
}
// 反序列化工具
public Club deserialize(final byte[] bytes) {
try {
Club club = deserializeInternal(bytes, schema.newMessage(), schema);
if (club != null) {
return club;
}
} catch (final Exception e) {
throw new IllegalStateException(e.getMessage(), e);
}
return null;
}
// 實際反序列化工具
private <T> T deserializeInternal(final byte[] bytes, final T result, final Schema<T> schema) {
ProtostuffIOUtil.mergeFrom(bytes, result, schema);
return result;
}
應用:
<!-- https://mvnrepository.com/artifact/io.protostuff/protostuff-core --> <dependency> <groupId>io.protostuff</groupId> <artifactId>protostuff-core</artifactId> <version>1.6.0</version> </dependency> <!-- https://mvnrepository.com/artifact/io.protostuff/protostuff-runtime --> <dependency> <groupId>io.protostuff</groupId> <artifactId>protostuff-runtime</artifactId> <version>1.6.0</version> </dependency>
package com.java.mailbox.utils; import io.protostuff.LinkedBuffer; import io.protostuff.ProtobufIOUtil; import io.protostuff.ProtostuffIOUtil; import io.protostuff.Schema; import io.protostuff.runtime.RuntimeSchema; /** * @Author: 束手就擒 * @Date: 18-8-25 下午8:05 * @Description: */ public class ObjectSerializeUtil { /** * 序列化 * @param o * @param <T> * @return */ @SuppressWarnings("unchecked") public static <T> byte[] serializer(T o) { Schema schema = RuntimeSchema.getSchema(o.getClass()); return ProtobufIOUtil.toByteArray(o, schema, LinkedBuffer.allocate(256)); } /** * 反序列化 * @param bytes * @param clazz * @param <T> * @return */ @SuppressWarnings("unchecked") public static <T> T deserializer(byte[] bytes, Class<T> clazz) { T obj = null; try { obj = clazz.newInstance(); Schema schema = RuntimeSchema.getSchema(obj.getClass()); ProtostuffIOUtil.mergeFrom(bytes, obj, schema); } catch (IllegalAccessException | InstantiationException e) { e.printStackTrace(); } return obj; } }
測試:
package com.java.mailbox.obj; import com.java.mailbox.utils.ObjectSerializeUtil; import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.test.context.junit4.SpringRunner; import java.util.Arrays; import static org.junit.Assert.*; /** * @Author: 束手就擒 * @Date: 18-8-25 下午8:36 * @Description: */ @RunWith(SpringRunner.class) @SpringBootTest public class StudentTest { @Test public void hhh() { Student student = Student.builder().userName("束手就擒") .userAge(20) .userGender("Male") .build(); byte[] serializate = ObjectSerializeUtil.serializer(student); System.out.println("serialize = "+ Arrays.toString(serializate)); Student studentB = ObjectSerializeUtil.deserializer(serializate,Student.class); System.out.println("studentB = "+studentB.toString()); } }
結果:
2018-08-25 21:05:00.045 INFO 7815 --- [ main] com.java.mailbox.obj.StudentTest : Started StudentTest in 11.407 seconds (JVM running for 14.519)
serialize = [10, 12, -26, -99, -97, -26, -119, -117, -27, -80, -79, -26, -109, -110, 18, 4, 77, 97, 108, 101, 24, 20]
studentB = Student(userName=束手就擒, userGender=Male, userAge=20)