洞察探索open banking如何通过小程序容器技术助力金融企业实现数据安全和数字化转型
1039
2022-10-20
Springboot集成ProtoBuf的实例
目录Springboot集成ProtoBuf1、pom.xml引入相关依赖2、新建序列化工具类ProtoBufUtil.java3、新建实体类User.java4、使用方式ProtoBuf+Java+Springboot+IDEA应用 什么是Protobuf应用环境开发环境
Springboot集成ProtoBuf
ProtoBuf是一种序列化和解析速度远高于jsON和XML的数据格式,项目中使用了CouchBase作为缓存服务器,从数据库中拿到数据后通过protobuf序列化后放入CouchBase作为缓存,查询数据的时候解压并反序列化成数据对象,下面是ProtoBuf的具体使用方法
1、pom.xml引入相关依赖
<http://;dependency>
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
private static Objenesis objenesis = new ObjenesisStd(true);
@SuppressWarnings("unchecked")
private static
Schema
if (schema == null) {
schema = RuntimeSchema.createFrom(cls);
if (schema != null) {
cachedSchema.put(cls, schema);
}
}
return schema;
}
public ProtoBufUtil() {
}
@SuppressWarnings({ "unchecked" })
public static
Class
LinkedBuffer buffer = LinkedBuffer.allocate(LinkedBuffer.DEFAULT_BUFFER_SIZE);
try {
Schema
return ProtostuffIOUtil.toByteArray(obj, schema, buffer);
} catch (Exception e) {
log.error("protobuf序列化失败");
throw new IllegalStateException(e.getMessage(), e);
} finally {
buffer.clear();
}
}
public static
try {
T message = (T) objenesis.newInstance(clazz);
Schema
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 bootaWVFvNlfS+IDEA+Windows
新建Spring boot项目 在IDEA开发工具中安装protobuf插件
添加配置maven依赖(可能一开始自己的项目中存在固有的配置,不要删除,在对应的地方添加下面的配置即可,不需要修改)
com.google.protobuf:protoc:3.1.0:exe:${os.detected.classifier}
写项目对应的.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
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 try{ XXX2.BaseInfo.Builder baseInfoBuilder = XXX2.BaseInfo.newBuilder(); baseInfoBuilder .setCompanyId(baseInfoList .get(i).getCompanyid()); baseInfoBuilder .setCompanyName(baseInfoList .get(i).getCompanyname()); baseInfoBuilder .setFlag(baseInfoList .get(i).getFlag()); baseInfoBuilder .setUpdateTime(baseInfoList .get(i).getUpdatetime()); for(int j=0;j<10;j++) { otipcBuilder.addBaseInfo(baseInfoBuilder .build()); } } catch (Exception e){ LoggerUtils.info(getClass(),e.getMessage()); } } listBuilder.addOtpic(otipcBuilder); 进行数据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 byte b = (byte) ((Integer.valueOf(String.valueOf(screateValue.charAt(j*2)), 16) << 4) | Integer.valueOf(String.valueOf(screateValue.charAt(j*2+1)), 16)); keyByte[j] = b; } Key secretKey= new SecretKeySpec(keyByte,"AES"); Security.addProvider(new org.bouncycastle.jce.provider.BouncyCastleProvider()); Cipher cipher= Cipher.getInstance("AES/ECB/PKCS7Padding", "BC"); cipher.init(Cipher.ENCRYPT_MODE, secretKey); data = cipher.doFinal(output.toByteArray()); sendPostJSON(screateKey, data); return "success"; } catch(Exception e){ e.printStackTrace(); } return null; } 小结一下:经验证,Protobuf 序列化相比XML,JSON性能更好,在Protobuf 官网看到在创建对象,将对象序列化为内存中的字节序列,然后再反序列化的整个过程中相比其他相似技术的性能测试结果图,但是在通用性上会存在局限性,功能相对简单,不适合用来描述数据结构。
try{
XXX2.BaseInfo.Builder baseInfoBuilder = XXX2.BaseInfo.newBuilder();
baseInfoBuilder .setCompanyId(baseInfoList .get(i).getCompanyid());
baseInfoBuilder .setCompanyName(baseInfoList .get(i).getCompanyname());
baseInfoBuilder .setFlag(baseInfoList .get(i).getFlag());
baseInfoBuilder .setUpdateTime(baseInfoList .get(i).getUpdatetime());
for(int j=0;j<10;j++) {
otipcBuilder.addBaseInfo(baseInfoBuilder .build());
}
}
catch (Exception e){
LoggerUtils.info(getClass(),e.getMessage());
}
}
listBuilder.addOtpic(otipcBuilder);
进行数据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 byte b = (byte) ((Integer.valueOf(String.valueOf(screateValue.charAt(j*2)), 16) << 4) | Integer.valueOf(String.valueOf(screateValue.charAt(j*2+1)), 16)); keyByte[j] = b; } Key secretKey= new SecretKeySpec(keyByte,"AES"); Security.addProvider(new org.bouncycastle.jce.provider.BouncyCastleProvider()); Cipher cipher= Cipher.getInstance("AES/ECB/PKCS7Padding", "BC"); cipher.init(Cipher.ENCRYPT_MODE, secretKey); data = cipher.doFinal(output.toByteArray()); sendPostJSON(screateKey, data); return "success"; } catch(Exception e){ e.printStackTrace(); } return null; } 小结一下:经验证,Protobuf 序列化相比XML,JSON性能更好,在Protobuf 官网看到在创建对象,将对象序列化为内存中的字节序列,然后再反序列化的整个过程中相比其他相似技术的性能测试结果图,但是在通用性上会存在局限性,功能相对简单,不适合用来描述数据结构。
byte b = (byte) ((Integer.valueOf(String.valueOf(screateValue.charAt(j*2)), 16) << 4) |
Integer.valueOf(String.valueOf(screateValue.charAt(j*2+1)), 16));
keyByte[j] = b;
}
Key secretKey= new SecretKeySpec(keyByte,"AES");
Security.addProvider(new org.bouncycastle.jce.provider.BouncyCastleProvider());
Cipher cipher= Cipher.getInstance("AES/ECB/PKCS7Padding", "BC");
cipher.init(Cipher.ENCRYPT_MODE, secretKey);
data = cipher.doFinal(output.toByteArray());
sendPostJSON(screateKey, data);
return "success";
} catch(Exception e){
e.printStackTrace();
}
return null;
}
小结一下:经验证,Protobuf 序列化相比XML,JSON性能更好,在Protobuf 官网看到在创建对象,将对象序列化为内存中的字节序列,然后再反序列化的整个过程中相比其他相似技术的性能测试结果图,但是在通用性上会存在局限性,功能相对简单,不适合用来描述数据结构。
版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。
发表评论
暂时没有评论,来抢沙发吧~