Protostuff序列化和反序列化的简单使用

什么是Protocol Buffer?

Protocol Buffer是谷歌出品的一种数据交换格式,独立于语言和平台,类似于json。Google提供了多种语言的实现:java、c++、go和python。对象序列化城Protocol Buffer之后可读性差,但是相比xml,json,它占用小,速度快。适合做数据存储或 RPC 数据交换格式

Java序列化库 - Protostuff

相对我们常用的json来说,Protocol Buffer门槛更高,因为需要编写.proto文件,再把它编译成目标语言,这样使用起来就很麻烦。但是现在有了protostuff之后,就不需要依赖.proto文件了,他可以直接对POJO进行序列化和反序列化,使用起来非常简单。

Demo

1、新建一个SpringBoot的项目,再引入Protostuff的依赖

      
           io.protostuff
           protostuff-core
           ${protostuff.version}
       

       
           io.protostuff
           protostuff-runtime
           ${protostuff.version}
       

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

@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;
}

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

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;
    }
}

4、验证序列化功能

@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());
    }
}

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

序列化后:[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))

参考

  • https://github.com/protostuff/protostuff

你可能感兴趣的:(Protostuff序列化和反序列化的简单使用)