从零学Netty(十二)Netty基于Protostuff(Protocol) 序列化
初探Protostuff的使用
最近看到了一个叫做Protostuff的库,是基于谷歌Protocal Buffer的序列化库,之前了解过Protocol Buffer,对学习了一些资料后,写了个demo
什么是Protocol Buffer?
Protocol Buffer是谷歌出品的一种数据交换格式,独立于语言和平台,类似于json。Google提供了多种语言的实现:java、c++、go和python。对象序列化城Protocol Buffer之后可读性差,但是相比xml,json,它占用小,速度快。适合做数据存储或 RPC 数据交换格式。
Java序列化库 - Protostuff
相对我们常用的json来说,Protocol Buffer门槛更高,因为需要编写.proto文件,再把它编译成目标语言,这样使用起来就很麻烦。但是现在有了protostuff之后,就不需要依赖.proto文件了,他可以直接对POJO进行序列化和反序列化,使用起来非常简单。
引入依赖
<dependency>
<groupId>io.protostuff</groupId>
<artifactId>protostuff-core</artifactId>
<version>1.7.2</version>
</dependency>
<dependency>
<groupId>io.protostuff</groupId>
<artifactId>protostuff-runtime</artifactId>
<version>1.7.2</version>
</dependency>
工具类
import io.protostuff.LinkedBuffer;
import io.protostuff.ProtostuffIOUtil;
import io.protostuff.Schema;
import io.protostuff.runtime.RuntimeSchema;
import java.util.Arrays;
import java.util.Map;
import java.util.Objects;
import java.util.concurrent.ConcurrentHashMap;
public class ProtostuffUtils {
/**
* 缓存Schema
*/
private static Map<Class<?>, Schema<?>> schemaCache = new ConcurrentHashMap<>();
/**
* 序列化方法,把指定对象序列化成字节数组
*
* @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);
LinkedBuffer buffer = LinkedBuffer.allocate(LinkedBuffer.DEFAULT_BUFFER_SIZE);
byte[] data;
try {
data = ProtostuffIOUtil.toByteArray(obj, schema, buffer);
} finally {
buffer.clear();
}
return data;
}
/**
* 反序列化方法,将字节数组反序列化成指定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进行懒创建并缓存
//所以可以一直调用RuntimeSchema.getSchema(),这个方法是线程安全的
schema = RuntimeSchema.getSchema(clazz);
if (Objects.nonNull(schema)) {
schemaCache.put(clazz, schema);
}
}
return schema;
}
public static void main(String[] args){
//创建一个user对象
User user = User.builder().id("1").age(20).name("张三").desc("programmer").build();
//创建一个Group对象
Group group = Group.builder().id("1").name("分组1").user(user).build();
//使用ProtostuffUtils序列化
byte[] groupdata = ProtostuffUtils.serialize(group);
System.out.println("序列化后:" + Arrays.toString(groupdata));
Group result = ProtostuffUtils.deserialize(groupdata, Group.class);
System.out.println("反序列化后:" + result.toString());
byte[] userdata = ProtostuffUtils.serialize(user);
System.out.println("序列化后:" + Arrays.toString(userdata));
User result2 = ProtostuffUtils.deserialize(userdata, User.class);
System.out.println("反序列化后:" + result2.toString());
}
}
对象类
@Data
@Builder
public class Group {
private String id;
private String name;
private User user;
}
@Data
@Builder
public class User {
private String id;
private String name;
private Integer age;
private String desc;
}
测试结果
结合netty应用
网上已经有了较好的文章 我就不造轮子了
netty结合Protostuff传输对象案例,单机压测秒级接收35万个对象
还没有评论,来说两句吧...