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

初探Protostuff的使用[通俗易懂]初探Protostuff的使用最近在学习RPC,看到了一个叫做Protostuff的库,是基于谷歌ProtocalBuffer的序列化库,之前了解过ProtocolBuffer,对学习了一些资料后,写了个demo,记录下来。什么是ProtocolBuffer?ProtocolBuffer是谷歌出品的一种数据交换格式,独立于语言和平台,类似于json。Google提供…

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

初探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。

参考

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

发布者:全栈程序员-用户IM,转载请注明出处:https://javaforall.cn/133960.html原文链接:https://javaforall.cn

【正版授权,激活自己账号】: Jetbrains全家桶Ide使用,1年售后保障,每天仅需1毛

【官方授权 正版激活】: 官方授权 正版激活 支持Jetbrains家族下所有IDE 使用个人JB账号...

(0)


相关推荐

  • 御用导航提示页面_终实现微信位置发送到汽车导航 越用越好用

    御用导航提示页面_终实现微信位置发送到汽车导航 越用越好用我们使用微信,其中一个非常好用的功能就是发送位置。在朋友聚会或者去朋友家做客时,只需朋友发送一个微信用微信位置,我们就非常清楚的得知目的地,直接把这个位置推送给手机里的导航软件,并发起导航。然而对于习惯使用中控屏导航的车友来说,这个过程脱节了。微信位置只能使用手机导航,不能直接推送到车载导航。手动输入,无疑更加烦躁,担心输错,还要确认好几次。在最新的高德地图车机版中,我们留意到更新中“手…

  • python中concat函数的用法及示例

    python中concat函数的用法及示例concat方法相当于数据库中的全连接(UNIONALL),可以指定按某个轴进行连接,也可以指定连接的方式join(outer,inner只有这两种)。与数据库不同的是concat不会去重,要达到去重的效果可以使用drop_duplicates方法concat(objs,axis=0,join=’outer’,join_axes=None,ignore_index=False,k…

  • openssl-heartbleed漏洞学习

    openssl-heartbleed漏洞学习了解漏洞Heartbleed漏洞:Heartbleed漏洞是openssl的一个漏洞,这个严重漏洞(CVE-2014-0160)的产生是由于未能在memcpy()调用受害用户输入内容作为长度参数之前正确进行边界检查。攻击者可以追踪OpenSSL所分配的64KB缓存、将超出必要范围的字节信息复制到缓存当中再返回缓存内容,这样一来受害者的内存内容就会以每次64KB的速度进行泄露。背景和影响:…

  • 列车调度(贪心)

    列车调度(贪心)#题目:火车站的列车调度铁轨的结构如下图所示。两端分别是一条入口(Entrance)轨道和一条出口(Exit)轨道,它们之间有N条平行的轨道。每趟列车从入口可以选择任意一条轨道进入,最后从出口离开。在图中有9趟列车,在入口处按照{8,4,2,5,3,9,1,6,7}的顺序排队等待进入(一条轨道可以停放多个火车)。如果要求它们必须按序号递减的顺序从出口离开,则至少需要多少条平行铁轨用于调度?输入格式…

  • 图像超分辨之RDN(Residual Dense Network)

    图像超分辨之RDN(Residual Dense Network) 论文:ResidualDenseNetworkforImageSuper-Resolution Github:https://github.com/yulunzhang/RDNhttps://github.com/hengchuan/RDN-TensorFlow 整体结构: RDN(ResidualDenseNetwork)主要包含4个模块。…

  • goland激活码2021【注册码】

    goland激活码2021【注册码】,https://javaforall.cn/100143.html。详细ieda激活码不妨到全栈程序员必看教程网一起来了解一下吧!

发表回复

您的电子邮箱地址不会被公开。

关注全栈程序员社区公众号