• 初探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的依赖

          <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注解可以让我们通过更加优雅的构建者模式来创建对象。

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

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

    public class ProtostuffUtils {
        /**
         * 避免每次序列化都重新申请Buffer空间
         */
        private static LinkedBuffer buffer = LinkedBuffer.allocate(LinkedBuffer.DEFAULT_BUFFER_SIZE);
        /**
         * 缓存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);
            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;
        }
    }
    

    验证序列化功能

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

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

    序列化后:[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://blog.csdn.net/oppo5630/article/details/80173520

  • 相关阅读:
    jquery多次上传同一张图片
    选中没有选中的复选框,匹配含有某个字符串的正则,json取值的两种方法,把变量定义在外面跟里面的区别
    点击div全选中再点击取消全选div里面的文字
    this指向问题
    js的querySelector跟querySelectorAll
    点击下箭头⤵️变上箭头⬆️来回切换的两种方法
    a标签的href值
    padding下中英文左右两端对齐
    map()函数
    设计模式
  • 原文地址:https://www.cnblogs.com/nsw2018/p/15714833.html
Copyright © 2020-2023  润新知