引入依赖
<dependency>
<groupId>io.netty</groupId>
<artifactId>netty-all</artifactId>
<version>4.1.70.Final</version> <!-- 或者是最新版本 -->
</dependency>
<!-- https://mvnrepository.com/artifact/com.esotericsoftware/kryo -->
<dependency>
<groupId>com.esotericsoftware</groupId>
<artifactId>kryo</artifactId>
<version>5.6.0</version>
</dependency>
<!-- https://mvnrepository.com/artifact/de.javakaffee/kryo-serializers -->
<dependency>
<groupId>de.javakaffee</groupId>
<artifactId>kryo-serializers</artifactId>
<version>0.45</version>
</dependency>
创建kryo对象,因为线程不安全因此需要每个线程持有一个对象
public abstract class KryoFactory {
private final static KryoFactory threadFactory = new ThreadLocalKryoFactory();
protected KryoFactory() {
}
public static KryoFactory getDefaultFactory() {
return threadFactory;
}
protected Kryo createKryo() {
Kryo kryo = new Kryo();
kryo.setRegistrationRequired(false);
kryo.register(Message.class);
kryo.register(BigDecimal.class, new DefaultSerializers.BigDecimalSerializer());
kryo.register(BigInteger.class, new DefaultSerializers.BigIntegerSerializer());
kryo.register(HashMap.class);
kryo.register(ArrayList.class);
kryo.register(LinkedList.class);
kryo.register(HashSet.class);
kryo.register(TreeSet.class);
kryo.register(Hashtable.class);
kryo.register(Date.class);
kryo.register(Calendar.class);
kryo.register(ConcurrentHashMap.class);
kryo.register(StringBuffer.class);
kryo.register(StringBuilder.class);
kryo.register(Object.class);
kryo.register(Object[].class);
kryo.register(String[].class);
kryo.register(byte[].class);
kryo.register(char[].class);
kryo.register(int[].class);
kryo.register(float[].class);
kryo.register(double[].class);
return kryo;
}
}
public class ThreadLocalKryoFactory extends KryoFactory {
private final ThreadLocal<Kryo> holder = new ThreadLocal<Kryo>() {
@Override
protected Kryo initialValue() {
return createKryo();
}
};
public Kryo getKryo() {
return holder.get();
}
public void removeKryo(){
holder.remove();
}
}
public class KryoSerializer {
private static final ThreadLocalKryoFactory factory = new ThreadLocalKryoFactory();
/**
* 注意该方法是用于带长度的编码专用,不可用于其它,如有需要请使用第二个serialize方法
* @param object
* @param out
*/
public static void serializeWithLength(Object object, ByteBuf buffer) {
Kryo kryo = factory.getKryo();
ByteArrayOutputStream baos = new ByteArrayOutputStream();
Output output = new Output(baos);
kryo.writeClassAndObject(output, object);
output.flush();
output.close();
byte[] b = baos.toByteArray();
try {
baos.flush();
baos.close();
} catch (IOException e) {
e.printStackTrace();
}
buffer.writeInt(b.length);
buffer.writeBytes(b);
}
public static void serialize(Object object, ByteBuf out) {
Kryo kryo = factory.getKryo();
ByteArrayOutputStream baos = new ByteArrayOutputStream();
Output output = new Output(baos);
kryo.writeClassAndObject(output, object);
output.flush();
output.close();
byte[] b = baos.toByteArray();
try {
baos.flush();
baos.close();
} catch (IOException e) {
e.printStackTrace();
}
out.writeBytes(b);
}
public static Object deserialize(ByteBuf in) {
if (in == null) {
return null;
}
Input input = new Input(new ByteBufInputStream(in));
Kryo kryo = factory.getKryo();
Object o = kryo.readClassAndObject(input);
return o;
}
}
自定义编解码器:
public class MessageCodec extends MessageToMessageCodec<ByteBuf, Message> {
private static final ThreadLocalKryoFactory factory = new ThreadLocalKryoFactory();
@Override
protected void encode(ChannelHandlerContext ctx, Message msg, List<Object> out) throws Exception {
ByteBuf buffer = ctx.alloc().buffer();
buffer.writeInt(1);//version
buffer.writeInt(msg.getSerdeType());//serializer type
buffer.writeInt(1);//指令类型
//3. 使用kryo序列化方式
KryoSerializer.serializeWithLength(msg,buffer);
out.add(buffer);
}
@Override
protected void decode(ChannelHandlerContext ctx, ByteBuf in, List<Object> out) throws Exception {
int version = in.readInt();
int serType = in.readInt();
int type = in.readInt();
int length = in.readInt();
//3. 使用kryo进行反序列化
Object message = KryoSerializer.deserialize(in);
out.add(message);
}
}
将该编解码器加入到pipline中,后面再加业务处理器即可得到反序列化的对象
实现
ChannelInboundHandlerAdapter类重写
channelRead即可得到反序列化的对象