天天看點

Springboot內建ProtoBuf

 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))