当我们利用protobuf传输的时候,我们需要定义.proto文件,再利用protobuf插件生成java类型。这是有点麻烦,有没有直接就可以转换的方法呢?当然是有的,protostudff提供了可以直接价格Object传输的方法,只要提供这个类的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);
}
}
}