當我們利用protobuf傳輸?shù)臅r候,我們需要定義.proto文件凸主,再利用protobuf插件生成java類型。這是有點麻煩额湘,有沒有直接就可以轉(zhuǎn)換的方法呢卿吐?當然是有的,protostudff提供了可以直接價格Object傳輸?shù)姆椒ǚ婊灰峁┻@個類的Schema嗡官。
<!-- https://mvnrepository.com/artifact/io.netty/netty-all -->
<dependency>
<groupId>io.netty</groupId>
<artifactId>netty-all</artifactId>
<version>4.1.32.Final</version>
</dependency>
<dependency>
<groupId>com.google.protobuf</groupId>
<artifactId>protobuf-java</artifactId>
<version>${protobuf.version}</version>
</dependency>
<dependency>
<groupId>io.protostuff</groupId>
<artifactId>protostuff-core</artifactId>
<version>1.6.0</version>
</dependency>
<dependency>
<groupId>io.protostuff</groupId>
<artifactId>protostuff-runtime</artifactId>
<version>1.6.0</version>
</dependency>
<!-- 用來new一個新類-->
<dependency>
<groupId>org.objenesis</groupId>
<artifactId>objenesis</artifactId>
<version>2.6</version>
</dependency>
import java.util.concurrent.ConcurrentHashMap;
public class SerializationUtil {
private static final ConcurrentHashMap<Class<?>, Schema<?>> map = new ConcurrentHashMap<>();
private static final LinkedBuffer linkedBuffer = LinkedBuffer.allocate(LinkedBuffer.DEFAULT_BUFFER_SIZE);
private static final Objenesis objenesis= new ObjenesisStd();
public static <T> byte[] serialize(T obj){
Class<?> aClass = obj.getClass();
Schema schema = getSchema(aClass);
byte[] data;
try {
data = ProtobufIOUtil.toByteArray(obj, schema, linkedBuffer);
}finally {
linkedBuffer.clear();
}
return data;
}
public static <T> T deserialize(byte[] bytes,Class<T> clazz){
try {
Schema schema = getSchema(clazz);
T o = objenesis.newInstance(clazz);
ProtobufIOUtil.mergeFrom(bytes, o, schema);
return o;
}catch (Exception e){
e.printStackTrace();
}
return null;
}
private static Schema getSchema(Class clazz){
Schema<?> schema = map.get(clazz);
if(schema==null){
schema= RuntimeSchema.getSchema(clazz);
if(schema!=null){
map.put(clazz,schema);
}
}
return schema;
}
}
編解碼器
public class ObjDecoder extends ByteToMessageDecoder {
private Class<?> clazz;
public ObjDecoder(Class clazz){
this.clazz=clazz;
}
@Override
protected void decode(ChannelHandlerContext ctx, ByteBuf in, List<Object> out) throws Exception {
if(in.readableBytes()<4){
return;
}
in.markReaderIndex();
int mslength= in.readInt();
if(in.readableBytes()<mslength){
in.resetReaderIndex();
return;
}
byte[] data= new byte[mslength];
in.readBytes(data);
out.add(SerializationUtil.deserialize(data,clazz));
}
}
public class ObjEncoder extends MessageToByteEncoder {
private Class<?> genericClass;
public ObjEncoder(Class<?> genericClass){
this.genericClass=genericClass;
}
@Override
protected void encode(ChannelHandlerContext ctx, Object msg, ByteBuf out) throws Exception {
if(genericClass.isInstance(msg)){
byte[] serialize = SerializationUtil.serialize(msg);
out.writeInt(serialize.length);
out.writeBytes(serialize);
}
}
}