使用Protostuff实现序列化与反序列化

使用Protostuff实现序列化与反序列化
(1)Protobuf介绍

Google Protocol Buffer( 简称 Protobuf) 是 Google 公司内部的混合语言数据标准,目前已经正在使用的有超过 48,162 种报文格式定义和超过 12,183 个 .proto 文件。他们用于 RPC 系统和持续数据存储系统。

Protocol Buffers 是一种轻便高效的结构化数据存储格式,可以用于结构化数据串行化,或者说序列化。它很适合做数据存储或 RPC 数据交换格式。可用于通讯协议、数据存储等领域的语言无关、平台无关、可扩展的序列化结构数据格式。目前提供了 C++、Java、Python 三种语言的 API。

(2)Protobuf优点

    平台无关,语言无关,可扩展;
    提供了友好的动态库,使用简单;
    解析速度快,比对应的XML快约20-100倍;
    序列化数据非常简洁、紧凑,与XML相比,其序列化之后的数据量约为1/3到1/10;
    独立于语言,独立于平台,最最重要的是它的效率相当高,用protobuf序列化后的大小是json的10分之一,xml格式的20分之一,是二进制序列化的10分之一,

(3)Protobuf主要流程

需要自己写一个.proto文件用来描述序列化的格式,然后用Protobuf提供的protoc工具将.proto文件编译成一个Java文件,最后将该Java文件引入到项目中就可以了。

(4)Protostuff介绍

google原生的protobuffer使用起来相当麻烦,首先要写.proto文件,然后编译.proto文件,生成对应的.java文件。protostuff基于Google Protobuf,好处就是不用自己写.proto文件同时在几乎不损耗性能的情况下即可实现对象的序列化与反序列化。

(5)使用Protostuff示例

Protostuff版本:

 

使用Protostuff实现Jedis中Club对象的读取:

    代码结构为:

序列化工具类ProtostuffSerializer 提供了序列化和反序列化方法:
 
    // 序列化工具
    public byte[] seriable(final Club club) {
        final LinkedBuffer linkedBuffer = LinkedBuffer.allocate(LinkedBuffer.DEFAULT_BUFFER_SIZE);
        try {
            return serializeInternal(club, schema, linkedBuffer);
        } catch (final Exception e) {
            throw new IllegalStateException(e.getMessage(), e);
        } finally {
            linkedBuffer.clear();
        }
    }
    
    // 实际序列化工具
    private <T> byte[] serializeInternal(final T source, final Schema<T> schema, final LinkedBuffer linkedBuffer) {
        return ProtostuffIOUtil.toByteArray(source, schema, linkedBuffer);
    }
    
    // 反序列化工具
    public Club deserialize(final byte[] bytes) {
        try {
            Club club = deserializeInternal(bytes, schema.newMessage(), schema);
            if (club != null) {
                return club;
            }
        } catch (final Exception e) {
            throw new IllegalStateException(e.getMessage(), e);
        }
        return null;
    }
    
    // 实际反序列化工具
    private <T> T deserializeInternal(final byte[] bytes, final T result, final Schema<T> schema) {
        ProtostuffIOUtil.mergeFrom(bytes, result, schema);
        return result;
    }

应用:

<!-- https://mvnrepository.com/artifact/io.protostuff/protostuff-core -->
<dependency>
    <groupId>io.protostuff</groupId>
    <artifactId>protostuff-core</artifactId>
    <version>1.6.0</version>
</dependency>

<!-- https://mvnrepository.com/artifact/io.protostuff/protostuff-runtime -->
<dependency>
    <groupId>io.protostuff</groupId>
    <artifactId>protostuff-runtime</artifactId>
    <version>1.6.0</version>
</dependency>
package com.java.mailbox.utils;

import io.protostuff.LinkedBuffer;
import io.protostuff.ProtobufIOUtil;
import io.protostuff.ProtostuffIOUtil;
import io.protostuff.Schema;
import io.protostuff.runtime.RuntimeSchema;

/**
 * @Author: 束手就擒
 * @Date: 18-8-25 下午8:05
 * @Description:
 */
public class ObjectSerializeUtil {
    /**
     * 序列化
     * @param o
     * @param <T>
     * @return
     */
    @SuppressWarnings("unchecked")
    public static <T> byte[] serializer(T o) {
        Schema schema = RuntimeSchema.getSchema(o.getClass());
        return ProtobufIOUtil.toByteArray(o, schema, LinkedBuffer.allocate(256));
    }

    /**
     * 反序列化
     * @param bytes
     * @param clazz
     * @param <T>
     * @return
     */
    @SuppressWarnings("unchecked")
    public static <T> T deserializer(byte[] bytes, Class<T> clazz) {

        T obj = null;
        try {
            obj = clazz.newInstance();
            Schema schema = RuntimeSchema.getSchema(obj.getClass());
            ProtostuffIOUtil.mergeFrom(bytes, obj, schema);
        } catch (IllegalAccessException | InstantiationException e) {
            e.printStackTrace();
        }
        return obj;
    }
}

 

测试:

package com.java.mailbox.obj;

import com.java.mailbox.utils.ObjectSerializeUtil;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;

import java.util.Arrays;

import static org.junit.Assert.*;

/**
 * @Author: 束手就擒
 * @Date: 18-8-25 下午8:36
 * @Description:
 */
@RunWith(SpringRunner.class)
@SpringBootTest
public class StudentTest {

    @Test
    public void hhh() {
        Student student = Student.builder().userName("束手就擒")
                .userAge(20)
                .userGender("Male")
                .build();

        byte[] serializate = ObjectSerializeUtil.serializer(student);
        System.out.println("serialize = "+ Arrays.toString(serializate));
        Student studentB = ObjectSerializeUtil.deserializer(serializate,Student.class);
        System.out.println("studentB = "+studentB.toString());

    }

}

结果:

2018-08-25 21:05:00.045  INFO 7815 --- [           main] com.java.mailbox.obj.StudentTest         : Started StudentTest in 11.407 seconds (JVM running for 14.519)
serialize = [10, 12, -26, -99, -97, -26, -119, -117, -27, -80, -79, -26, -109, -110, 18, 4, 77, 97, 108, 101, 24, 20]
studentB = Student(userName=束手就擒, userGender=Male, userAge=20)

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

来日可期1314

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值