初探Protostuff的使用[通俗易懂]

初探Protostuff的使用[通俗易懂]

大家好,又见面了,我是你们的朋友全栈君。

初探Protostuff的使用 最近在学习RPC,看到了一个叫做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进行序列化和反序列化,使用起来非常简单。

实战新建一个SpringBoot的项目,再引入Protostuff的依赖

代码语言:javascript代码运行次数:0运行复制

io.protostuff

protostuff-core

${protostuff.version}

io.protostuff

protostuff-runtime

${protostuff.version}

先编写两个POJO,再把它们嵌套起来,这里使用了lombok的@Data注解和@Builder注解,@Data可以自动生成getter setter,@Builder注解可以让我们通过更加优雅的构建者模式来创建对象。

代码语言:javascript代码运行次数:0运行复制@Data

@Builder

public class User {

private String id;

private String name;

private Integer age;

private String desc;

}代码语言:javascript代码运行次数:0运行复制@Data

@Builder

public class Group {

private String id;

private String name;

private User user;

}接下来编写Protostuff序列化工具类

代码语言:javascript代码运行次数:0运行复制public class ProtostuffUtils {

/** * 避免每次序列化都重新申请Buffer空间 */

private static LinkedBuffer buffer = LinkedBuffer.allocate(LinkedBuffer.DEFAULT_BUFFER_SIZE);

/** * 缓存Schema */

private static Map, Schema> schemaCache = new ConcurrentHashMap<>();

/** * 序列化方法,把指定对象序列化成字节数组 * * @param obj * @param * @return */

@SuppressWarnings("unchecked")

public static byte[] serialize(T obj) {

Class clazz = (Class) obj.getClass();

Schema schema = getSchema(clazz);

byte[] data;

try {

data = ProtostuffIOUtil.toByteArray(obj, schema, buffer);

} finally {

buffer.clear();

}

return data;

}

/** * 反序列化方法,将字节数组反序列化成指定Class类型 * * @param data * @param clazz * @param * @return */

public static T deserialize(byte[] data, Class clazz) {

Schema schema = getSchema(clazz);

T obj = schema.newMessage();

ProtostuffIOUtil.mergeFrom(data, obj, schema);

return obj;

}

@SuppressWarnings("unchecked")

private static Schema getSchema(Class clazz) {

Schema schema = (Schema) 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;

}

}验证序列化功能

代码语言:javascript代码运行次数:0运行复制@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 {

//创建一个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[] data = ProtostuffUtils.serialize(group);

System.out.println("序列化后:" + Arrays.toString(data));

Group result = ProtostuffUtils.deserialize(data, Group.class);

System.out.println("反序列化后:" + result.toString());

}

}可以看到控制台打印出如下数据,说明序列化和反序列化成功

代码语言:javascript代码运行次数:0运行复制序列化后:[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))最后,代码在这里地址,欢迎star。

参考https://github.com/protostuff/protostuff发布者:全栈程序员栈长,转载请注明出处:https://javaforall.cn/133960.html原文链接:https://javaforall.cn

相关推荐

什么是mdl文件,如何打开mdl文件?
365beat网页怎么打不开

什么是mdl文件,如何打开mdl文件?

📅 09-21 👁️ 7252
双喜香烟价格表
365平台靠谱吗

双喜香烟价格表

📅 07-01 👁️ 2937
英雄联盟—源计划艾希
365网络电视直播

英雄联盟—源计划艾希

📅 07-28 👁️ 2819