ProtoBuf是一种序列化和解析速度远高于JSON和XML的数据格式,项目中使用了CouchBase作为缓存服务器,从数据库中拿到数据后通过protobuf序列化后放入CouchBase作为缓存,查询数据的时候解压并反序列化成数据对象,下面是ProtoBuf的具体使用方法
1、pom.xml引入相关依赖
<dependency>
<groupId>com.google.protobuf</groupId>
<artifactId>protobuf-java</artifactId>
<version>3.5.0</version>
</dependency>
<dependency>
<groupId>io.protostuff</groupId>
<artifactId>protostuff-core</artifactId>
<version>1.4.0</version>
</dependency>
<dependency>
<groupId>io.protostuff</groupId>
<artifactId>protostuff-runtime</artifactId>
<version>1.4.0</version>
</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<Class<?>, Schema<?>> cachedSchema = new ConcurrentHashMap<Class<?>, Schema<?>>();
private static Objenesis objenesis = new ObjenesisStd(true);
@SuppressWarnings("unchecked")
private static <T> Schema<T> getSchema(Class<T> cls) {
Schema<T> schema = (Schema<T>) 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 <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))