背景
在使用protostuff進行序列化的時候,不幸地遇到了一個問題,就是timestamp作為字段的時候,轉換出現問題,通過protostuff轉換後的結果都是1970-01-01 08:00:00,這就造成了timestamp不能夠序列化。于是google了一番,得知可以用delegate來解決這個問題。
原來的代碼
protobuffercodec類
import java.lang.reflect.constructor;
import java.util.map;
import java.util.concurrent.concurrenthashmap;
import io.protostuff.linkedbuffer;
import io.protostuff.protostuffioutil;
import io.protostuff.schema;
import io.protostuff.runtime.runtimeschema;
public class protobuffercodec implements codec {
private static map<class<?>, schema<?>> cachedschema = new concurrenthashmap<>();
public protobuffercodec() {
}
@override
public short getid() {
return codecs.protobuffer_codec;
@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 <t> byte[] encode(t obj) {
if (obj == null) {
return null;
class<t> cls = (class<t>) obj.getclass();
linkedbuffer buffer = linkedbuffer.allocate(linkedbuffer.default_buffer_size);
try {
schema<t> schema = getschema(cls);
byte[] bytes = protostuffioutil.tobytearray(obj, schema, buffer);
return bytes;
} catch (exception e) {
throw new illegalstateexception(e.getmessage(), e);
} finally {
buffer.clear();
public <t> t decode(byte[] bytes, class<t> clazz) {
if (bytes == null || bytes.length == 0) {
constructor<t> constructor = clazz.getconstructor();
constructor.setaccessible(true);
t message = constructor.newinstance();
schema<t> schema = getschema(clazz);
protostuffioutil.mergefrom(bytes, message, schema);
return message;
codec接口
/**
* 編解碼器
* @author jiujie
* @version $id: codec.java, v 0.1 2016年3月31日 上午11:39:14 jiujie exp $
*/
public interface codec {
* 編解碼器id,用于辨別編解碼器
* 2016年3月31日 上午11:38:39
* @return
public short getid();
* 把對象資料結構編碼成一個databuffer
* @param <t>
public <t> byte[] encode(t obj);
* 把databuffer解包構造一個對象
public <t> t decode(byte[] bytes, class<t> clazz);
修改後的代碼
import java.sql.timestamp;
import io.protostuff.runtime.defaultidstrategy;
import io.protostuff.runtime.delegate;
import io.protostuff.runtime.runtimeenv;
* protobuffer編解碼
* @version $id: protobuffercodec.java, v 0.1 2016年7月20日 下午1:52:41 jiujie exp $
/** 時間戳轉換delegate,解決時間戳轉換後錯誤問題 @author jiujie 2016年7月20日 下午1:52:25 */
private final static delegate<timestamp> timestamp_delegate = new timestampdelegate();
private final static defaultidstrategy idstrategy = ((defaultidstrategy) runtimeenv.id_strategy);
private final static concurrenthashmap<class<?>, schema<?>> cachedschema = new concurrenthashmap<>();
static {
idstrategy.registerdelegate(timestamp_delegate);
public static <t> schema<t> getschema(class<t> clazz) {
schema<t> schema = (schema<t>) cachedschema.get(clazz);
schema = runtimeschema.createfrom(clazz, idstrategy);
cachedschema.put(clazz, schema);
//改為由schema來執行個體化解碼對象,沒有構造函數也沒有問題
t message = schema.newmessage();
timestampdelegate類
import java.io.ioexception;
import io.protostuff.input;
import io.protostuff.output;
import io.protostuff.pipe;
import io.protostuff.wireformat.fieldtype;
* protostuff timestamp delegate
* @version $id: timestampdelegate.java, v 0.1 2016年7月20日 下午2:08:11 jiujie exp $
public class timestampdelegate implements delegate<timestamp> {
public fieldtype getfieldtype() {
return fieldtype.fixed64;
public class<?> typeclass() {
return timestamp.class;
public timestamp readfrom(input input) throws ioexception {
return new timestamp(input.readfixed64());
public void writeto(output output, int number, timestamp value,
boolean repeated) throws ioexception {
output.writefixed64(number, value.gettime(), repeated);
public void transfer(pipe pipe, input input, output output, int number,
output.writefixed64(number, input.readfixed64(), repeated);