一笑窜、Protostuff簡介
??Protocol Buffer是谷歌出品的一種數(shù)據(jù)交換格式致燥,獨(dú)立于語言和平臺登疗,類似于json。Google提供了多種語言的實現(xiàn):java嫌蚤、c++辐益、go和python。對象序列化城Protocol Buffer之后可讀性差脱吱,但是相比xml智政,json,它占用小箱蝠,速度快续捂。適合做數(shù)據(jù)存儲或 RPC 數(shù)據(jù)交換格式。
Java序列化庫 - Protostuff
相對我們常用的json來說宦搬,Protocol Buffer門檻更高牙瓢,因為需要編寫.proto文件,再把它編譯成目標(biāo)語言间校,這樣使用起來就很麻煩矾克。但是現(xiàn)在有了protostuff之后,就不需要依賴.proto文件了憔足,他可以直接對POJO進(jìn)行序列化和反序列化胁附,使用起來非常簡單酒繁。
二、Maven依賴
<dependency>
<groupId>io.protostuff</groupId>
<artifactId>protostuff-core</artifactId>
<version>${protostuff.version}</version>
</dependency>
<dependency>
<groupId>io.protostuff</groupId>
<artifactId>protostuff-runtime</artifactId>
<version>${protostuff.version}</version>
</dependency>
三控妻、
先編寫兩個POJO州袒,再把它們嵌套起來,這里使用了lombok的@Data注解和@Builder注解弓候,@Data可以自動生成getter setter稳析,@Builder注解可以讓我們通過更加優(yōu)雅的構(gòu)建者模式來創(chuàng)建對象。
@Data
@Builder
public class User {
private String id;
private String name;
private Integer age;
private String desc;
}
@Data
@Builder
public class Group {
private String id;
private String name;
private User user;
}
public class ProtostuffUtils {
/**
* 避免每次序列化都重新申請Buffer空間
*/
private static LinkedBuffer buffer = LinkedBuffer.allocate(LinkedBuffer.DEFAULT_BUFFER_SIZE);
/**
* 緩存Schema
*/
private static Map<Class<?>, Schema<?>> schemaCache = new ConcurrentHashMap<>();
/**
* 序列化方法弓叛,把指定對象序列化成字節(jié)數(shù)組
*
* @param obj
* @param <T>
* @return
*/
@SuppressWarnings("unchecked")
public static <T> byte[] serialize(T obj) {
Class<T> clazz = (Class<T>) obj.getClass();
Schema<T> schema = getSchema(clazz);
byte[] data;
try {
data = ProtostuffIOUtil.toByteArray(obj, schema, buffer);
} finally {
buffer.clear();
}
return data;
}
/**
* 反序列化方法彰居,將字節(jié)數(shù)組反序列化成指定Class類型
*
* @param data
* @param clazz
* @param <T>
* @return
*/
public static <T> T deserialize(byte[] data, Class<T> clazz) {
Schema<T> schema = getSchema(clazz);
T obj = schema.newMessage();
ProtostuffIOUtil.mergeFrom(data, obj, schema);
return obj;
}
@SuppressWarnings("unchecked")
private static <T> Schema<T> getSchema(Class<T> clazz) {
Schema<T> schema = (Schema<T>) schemaCache.get(clazz);
if (Objects.isNull(schema)) {
//這個schema通過RuntimeSchema進(jìn)行懶創(chuàng)建并緩存
//所以可以一直調(diào)用RuntimeSchema.getSchema(),這個方法是線程安全的
schema = RuntimeSchema.getSchema(clazz);
if (Objects.nonNull(schema)) {
schemaCache.put(clazz, schema);
}
}
return schema;
}
}
驗證序列化功能
@SpringBootApplication
public class Application implements CommandLineRunner {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
@Override
public void run(String... strings) throws Exception {
//創(chuàng)建一個user對象
User user = User.builder().id("1").age(20).name("張三").desc("programmer").build();
//創(chuàng)建一個Group對象
Group group = Group.builder().id("1").name("分組1").user(user).build();
//使用ProtostuffUtils序列化
byte[] data = ProtostuffUtils.serialize(group);
System.out.println("序列化后:" + Arrays.toString(data));
Group result = ProtostuffUtils.deserialize(data, Group.class);
System.out.println("反序列化后:" + result.toString());
}
}
可以看到控制臺打印出如下數(shù)據(jù),說明序列化和反序列化成功
序列化后:[10, 1, 49, 18, 7, -27, -120, -122, -25, -69, -124, 49, 27, 10, 1, 49, 18, 6, -27, -68, -96, -28, -72, -119, 24, 20, 34, 10, 112, 114, 111, 103, 114, 97, 109, 109, 101, 114, 28]
反序列化后:Group(id=1, name=分組1, user=User(id=1, name=張三, age=20, desc=programmer))