springboot prototype,
目录
跳靴集成ProtoBuf1、pom.xml引入相关依赖2、新建序列化工具类ProtoBufUtil.java3,新建实体类User.java4、使用方式爪哇跳羚理念应用什么是工具应用环境开发环境
Springboot集成ProtoBuf
ProtoBuf是一种序列化和解析速度远高于数据和可扩展置标语言的数据格式,项目中使用了命令作为缓存服务器,从数据库中拿到数据后通过工具序列化后放入命令作为缓存,查询数据的时候解压并反序列化成数据对象,下面是工具的具体使用方法
1、pom.xml引入相关依赖
依赖关系groupIdcom.google.protobuf/groupId artifactIdprotobuf-Java/artifactId版本3 .5 .0/版本/依赖项依赖关系groupIdio.protostuff/groupId artifactId proto stuff-core/artifactId版本1 . 4 . 0/版本/依赖性依赖关系groupIdio.protostuff/groupId artifactidprotostuf-运行时/artifactId版本1 .4 .0/版本/依赖项
2、新建序列化工具类ProtoBufUtil.java
包com。xrq。演示。utils导入Java。util。地图;导入Java。util。并发。并发hashmap导入org。slf4j。记录者;导入org。SLF 4j。伐木工厂;导入org。spring框架。objenesis。objenesis导入org。spring框架。objenesis。objenesisstd导入io。原型的东西。链接缓冲区;导入io。原始材料。原始材料;导入io。原型的东西。图式;导入io。原型的东西。运行时。运行时架构;/*** ProtoBufUtil转换工具类* * @ author XRQ * */public class ProtoBufUtil { private static Logger log=Logger factory。获取记录器(ProtoBufUtil。类);私有静态MapClass?图式?缓存模式=新的并发hashmap类?图式?();私有静态Objenesis Objenesis=new ObjenesisStd(true);@SuppressWarnings(未选中)私有静态t schema get schema(ClassT cls){ schema schema=(SchemaT)缓存的架构。get(cls);if(schema==null){ schema=运行时架构。从(cls)创建;if (schema!=null) { cachedSchema.put(cls,schema);} }返回架构;} public ProtoBufUtil(){ } @取消警告
({ "unchecked" }) public static <T> byte[] serializer(T obj) { Class<T> cls = (Class<T>) obj.getClass(); LinkedBuffer buffer = LinkedBuffer.allocate(LinkedBuffer.DEFAULT_BUFFER_SIZE); try { Schema<T> 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> T deserializer(byte[] bytes, Class<T> clazz) { try { T message = (T) objenesis.newInstance(clazz); Schema<T> 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依赖(可能一开始自己的项目中存在固有的配置,不要删除,在对应的地方添加下面的配置即可,不需要修改)
<dependency><groupId>io.protostuff</groupId><artifactId>protostuff-runtime</artifactId><version>1.4.0</version></dependency>
<plugin><groupId>org.xolstice.maven.plugins</groupId><artifactId>protobuf-maven-plugin</artifactId><version>0.5.0</version><configuration><protocArtifact>com.google.protobuf:protoc:3.1.0:exe:${os.detected.classifier}</protocArtifact><pluginId>grpc-java</pluginId></configuration><executions><execution><goals><goal>compile</goal> <goal>compile-custom</goal> </goals> </execution> </executions></plugin>
写项目对应的.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<BaseInfo> 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<baseInfoList .size();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<screateValue.length()/2;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 官网看到在创建对象,将对象序列化为内存中的字节序列,然后再反序列化的整个过程中相比其他相似技术的性能测试结果图,但是在通用性上会存在局限性,功能相对简单,不适合用来描述数据结构。
以上为个人经验,希望能给大家一个参考,也希望大家多多支持盛行IT。
郑重声明:本文由网友发布,不代表盛行IT的观点,版权归原作者所有,仅为传播更多信息之目的,如有侵权请联系,我们将第一时间修改或删除,多谢。