学无先后,达者为师

网站首页 java综合 正文

Springboot集成ProtoBuf的实例_java

作者:xrq0508   更新时间: 2022-05-18 java综合

Springboot集成ProtoBuf

ProtoBuf是一种序列化和解析速度远高于JSON和XML的数据格式,项目中使用了CouchBase作为缓存服务器,从数据库中拿到数据后通过protobuf序列化后放入CouchBase作为缓存,查询数据的时候解压并反序列化成数据对象,下面是ProtoBuf的具体使用方法

1、pom.xml引入相关依赖


    com.google.protobuf
    protobuf-java
    3.5.0


    io.protostuff
    protostuff-core
    1.4.0


    io.protostuff
    protostuff-runtime
    1.4.0

2、新建序列化工具类ProtoBufUtil.java

package com.xrq.demo.utils; 
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
 
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.objenesis.Objenesis;
import org.springframework.objenesis.ObjenesisStd;
 
import io.protostuff.LinkedBuffer;
import io.protostuff.ProtostuffIOUtil;
import io.protostuff.Schema;
import io.protostuff.runtime.RuntimeSchema;
 
/**
 * ProtoBufUtil 转换工具类
 * 
 * @author XRQ
 *
 */
public class ProtoBufUtil {
    private static Logger log = LoggerFactory.getLogger(ProtoBufUtil.class);
    private static Map, Schema> cachedSchema = new ConcurrentHashMap, Schema>();
 
    private static Objenesis objenesis = new ObjenesisStd(true);
 
    @SuppressWarnings("unchecked")
    private static  Schema getSchema(Class cls) {
        Schema schema = (Schema) cachedSchema.get(cls);
        if (schema == null) {
            schema = RuntimeSchema.createFrom(cls);
            if (schema != null) {
                cachedSchema.put(cls, schema);
            }
        }
        return schema;
    }
 
    public ProtoBufUtil() {
    }
 
    @SuppressWarnings({ "unchecked" })
    public static  byte[] serializer(T obj) {
        Class cls = (Class) obj.getClass();
        LinkedBuffer buffer = LinkedBuffer.allocate(LinkedBuffer.DEFAULT_BUFFER_SIZE);
        try {
            Schema schema = getSchema(cls);
            return ProtostuffIOUtil.toByteArray(obj, schema, buffer);
        } catch (Exception e) {
            log.error("protobuf序列化失败");
            throw new IllegalStateException(e.getMessage(), e);
        } finally {
            buffer.clear();
        }
    }
 
    public static  T deserializer(byte[] bytes, Class clazz) {
        try {
            T message = (T) objenesis.newInstance(clazz);
            Schema schema = getSchema(clazz);
            ProtostuffIOUtil.mergeFrom(bytes, message, schema);
            return message;
        } catch (Exception e) {
            log.error("protobuf反序列化失败");
            throw new IllegalStateException(e.getMessage(), e);
        }
    }
 
}

3、新建实体类User.java

注:重点是@Tag标签需要按照顺序往下排,如果需要新增字段,只能接着往下排,不能改变已存在的标签序号

package com.xrq.demo.bo; 
import java.io.Serializable;
import java.util.Date;  
import io.protostuff.Tag;
 
/**
 * 用户信息类
 * 
 * @ClassName: User
 * @author XRQ
 * @date 2019年4月30日
 */
public class User implements Serializable
{
    private static final long serialVersionUID = 1L;
 
    // 用户ID
    @Tag(1)
    private int userId;
 
    // 用户类型
    @Tag(2)
    private int userTypeId;
 
    // 用户名 
    @Tag(3)
    private String userName;
 
    // 创建时间
    @Tag(4)
    private Date createDateTime; 
    public int getUserId()
    {
 
        return userId;
    }
 
    public void setUserId(int userId)
    {
 
        this.userId = userId;
    }
 
    public int getUserTypeId()
    {
 
        return userTypeId;
    }
 
    public void setUserTypeId(int userTypeId)
    {
 
        this.userTypeId = userTypeId;
    }
 
    public String getUserName()
    {
 
        return userName;
    }
 
    public void setUserName(String userName)
    {
 
        this.userName = userName;
    }
 
    public Date getCreateDateTime()
    {
 
        return createDateTime;
    }
 
    public void setCreateDateTime(Date createDateTime)
    {
 
        this.createDateTime = createDateTime;
    }
}

4、使用方式

User user = new User();
user.setUserId(1);
user.setUserTypeId(1);
user.setUserName("XRQ");
user.setCreateDateTime(new Date());
//序列化成ProtoBuf数据结构
byte[] userProtoObj= ProtoBufUtil.serializer(userInfo)
 
//ProtoBuf数据结构反序列化成User对象
User newUserObj = ProtoBufUtil.deserializer(userProtoObj, User.class))

ProtoBuf+Java+Springboot+IDEA应用 

什么是Protobuf

1.Google Protocol Buffer( 简称 Protobuf) 是 Google 公司内部的混合语言数据标准;

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

3.形式为.proto结尾的文件;

应用环境

近期接触公司的网约车接口对接项目,第三方公司限定了接口的数据用protobuf格式序列化后,通过AES128加密后传输。

开发环境

Java+Spring boot+IDEA+Windows

新建Spring boot项目 在IDEA开发工具中安装protobuf插件

添加配置maven依赖(可能一开始自己的项目中存在固有的配置,不要删除,在对应的地方添加下面的配置即可,不需要修改)


	io.protostuff
	protostuff-runtime
	1.4.0


	org.xolstice.maven.plugins
	protobuf-maven-plugin
	0.5.0
	
	
		com.google.protobuf:protoc:3.1.0:exe:${os.detected.classifier}
	
	grpc-java
	
	
		
			
				compile
                compile-custom
            
        
    

写项目对应的.proto文件(这里贴一部分代码)

// 版本号
syntax = "proto2";
// 打包路径
option java_package="XXX1";
// Java文件名
option java_outer_classname="XXX2";
// 属性信息
message BaseInfo {
	// 公司标识
	required string CompanyId       = 1;
	// 公司名称
	required string CompanyName     = 2;
    // 操作标识
	required uint32 Flag            = 3;
	// 更新时间
	required uint64 UpdateTime      = 4;
}

.proto文件存在项目路径

生成.java文件方式(点击项目中的.proto文件,找到对应的maven依赖,双击标识2对应的protobuf:compile文件)

运行成功之后在对应路径下查看生成的.java文件

生成的Java文件即可使用(如果在业务中.proto文件很大,生成的Java大小超出IDEA默认的2.5M,生成的Java文件将被IDEA误认为不是Java文件,导致生成的Java文件不可使用,这时需要修改IDEA的配置文件,将默认的大小修改,重启IDEA即可) 进行数据序列化

List baseInfoList = baseInfoMapper.selectAll();
XXX2.OTIpcList.Builder listBuilder = XXX2.OTIpcList.newBuilder();
XXX2.OTIpc.Builder otipcBuilder = XXX2.OTIpc.newBuilder();
otipcBuilder.setCompanyId(ProjectConstant.COMPANY_ID);
otipcBuilder.setSource(ProjectConstant.COMPANY_SOURCE);
otipcBuilder.setIPCType(OTIpcDef.IpcType.baseInfoCompany);
for(int i=0;i

进行数据AES128位加密

public static String sendScreate(OTIpcDef.OTIpcList.Builder listBuilder) {
        String screateKeyString = getSecretKey();
        String screateKey = screateKeyString.split(";")[1];
        String screateValue = screateKeyString.split(";")[0];
        OTIpcDef.OTIpcList list = listBuilder.build();
        ByteArrayOutputStream output = new ByteArrayOutputStream();
        try {
            list.writeTo(output);
        } catch (IOException e) {
            e.printStackTrace();
        }
        byte[] data = null;
        try{
            byte[] keyByte = new byte[screateValue.length()/2];
            for(int j=0;j

小结一下:经验证,Protobuf 序列化相比XML,JSON性能更好,在Protobuf 官网看到在创建对象,将对象序列化为内存中的字节序列,然后再反序列化的整个过程中相比其他相似技术的性能测试结果图,但是在通用性上会存在局限性,功能相对简单,不适合用来描述数据结构。

原文链接:https://blog.csdn.net/xrq0508/article/details/89704159

栏目分类
最近更新