使用消息队列不可避免类和字节数组间转换,要使用JDK的序列化,前提条件是要实现Serializable接口。实现Serializable接口非常简单,就是定义一个常量而已。实在搞不懂这样的设计是为什么?但是既然如此,就不得不这样做。
但是很多类都没有做这个虽然简单,但是就因为简单而没有做的实现Serializable的步骤,这种情况下,如何做类和字节数组的转换?
其中之一就是使用Kryo,不废话了,直接上实现:
<dependency>
<groupId>com.esotericsoftware</groupId>
<artifactId>kryo</artifactId>
<version>5.5.0</version>
</dependency>
package org.qlm.util;
import com.esotericsoftware.kryo.Kryo;
import com.esotericsoftware.kryo.io.Input;
import com.esotericsoftware.kryo.io.Output;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
public class KryoUtils {
private static final ThreadLocal<Kryo> KRYO_THREAD_LOCAL = ThreadLocal.withInitial(() -> {
Kryo kryo = new Kryo();
kryo.setRegistrationRequired(false); // 不需要强制注册类
kryo.setReferences(true); // 支持对象引用(循环引用)
return kryo;
});
public static Kryo getKryo() {
return KRYO_THREAD_LOCAL.get();
}
/**
* 对象转字节数组
* @param obj 待转换对象
* @return 字节数组
*/
public static byte[] serialize(Object obj) {
if (obj == null) {
return new byte[0];
}
// 从当前线程获取 Kryo 实例
Kryo kryo = getKryo();
// 修复:将 Output 也纳入 try-with-resources,确保资源完全释放
try (ByteArrayOutputStream bos = new ByteArrayOutputStream();
Output output = new Output(bos)) {
kryo.writeObject(output, obj);
output.flush();
return bos.toByteArray();
} catch (Exception e) {
throw new RuntimeException("Kryo序列化失败", e);
}
}
/**
* 字节数组转对象
* @param bytes 字节数组
* @param clazz 目标类类型
* @return 还原后的对象
*/
public static <T> T deserialize(byte[] bytes, Class<T> clazz) {
if (bytes == null || bytes.length == 0) {
return null;
}
// 从当前线程获取 Kryo 实例
Kryo kryo = getKryo();
// 修复:将 Input 也纳入 try-with-resources,确保资源完全释放
try (ByteArrayInputStream bis = new ByteArrayInputStream(bytes);
Input input = new Input(bis)) {
return kryo.readObject(input, clazz);
} catch (Exception e) {
throw new RuntimeException("Kryo反序列化失败", e);
}
}
// 可选:手动移除当前线程的 Kryo 实例(比如线程池复用线程时,避免内存泄漏)
public static void removeKryo() {
KRYO_THREAD_LOCAL.remove();
}
}