package github.javaguide.serialize.kyro; import com.esotericsoftware.kryo.Kryo; import com.esotericsoftware.kryo.io.Input; import com.esotericsoftware.kryo.io.Output; import github.javaguide.dto.RpcRequest; import github.javaguide.dto.RpcResponse; import github.javaguide.exception.SerializeException; import github.javaguide.serialize.Serializer; import github.javaguide.transport.netty.NettyClientHandler; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; /** * @author shuang.kou * @createTime 2020年05月13日 19:29:00 */ public class KryoSerializer implements Serializer { private static final Logger logger = LoggerFactory.getLogger(KryoSerializer.class); /** * 由于 Kryo 不是线程安全的。每个线程都应该有自己的 Kryo,Input 和 Output 实例。 * 所以,使用 ThreadLocal 存放 Kryo 对象 */ private static final ThreadLocal kryoThreadLocal = ThreadLocal.withInitial(() -> { Kryo kryo = new Kryo(); kryo.register(RpcResponse.class); kryo.register(RpcRequest.class); kryo.setReferences(true);//默认值为true,是否关闭注册行为,关闭之后可能存在序列化问题,一般推荐设置为 true kryo.setRegistrationRequired(false);//默认值为false,是否关闭循环引用,可以提高性能,但是一般不推荐设置为 true return kryo; }); @Override public byte[] serialize(Object obj) { try (ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream(); Output output = new Output(byteArrayOutputStream)) { Kryo kryo = kryoThreadLocal.get(); // Object->byte:将对象序列化为byte数组 kryo.writeObject(output, obj); kryoThreadLocal.remove(); return output.toBytes(); } catch (Exception e) { logger.error("occur exception when serialize:", e); throw new SerializeException("序列化失败"); } } @Override public T deserialize(byte[] bytes, Class clazz) { try (ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(bytes); Input input = new Input(byteArrayInputStream)) { Kryo kryo = kryoThreadLocal.get(); // byte->Object:从byte数组中反序列化出对对象 Object o = kryo.readObject(input, clazz); kryoThreadLocal.remove(); return clazz.cast(o); } catch (Exception e) { logger.error("occur exception when deserialize:", e); throw new SerializeException("反序列化失败"); } } }