protostuff的坑
1、Protostuff 序列化/反序列化集合等对象
定义一个包装类:
public class SerializeDeserializeWrapper<T> { private T data; public static <T> SerializeDeserializeWrapper<T> builder(T data) { SerializeDeserializeWrapper<T> wrapper = new SerializeDeserializeWrapper<>(); wrapper.setData(data); return wrapper; } public T getData() { return data; } public void setData(T data) { this.data = data; } }
序列化是判断下,哪些不支持的集合,放在包装器里
@SuppressWarnings("unchecked") public static <T> byte[] serialize(T obj) { Class<T> clazz = (Class<T>) obj.getClass(); LinkedBuffer buffer = LinkedBuffer.allocate(LinkedBuffer.DEFAULT_BUFFER_SIZE); try { Object serializeObject = obj; Schema schema = WRAPPER_SCHEMA; if (!WRAPPER_SET.contains(clazz)) { schema = getSchema(clazz); } else { serializeObject = SerializeDeserializeWrapper.builder(obj); } return ProtostuffIOUtil.toByteArray(serializeObject, schema, buffer); } catch (Exception e) { logger.error("序列化对象异常 [" + obj + "]", e); throw new IllegalStateException(e.getMessage(), e); } finally { buffer.clear(); } }
还有要注意的:
1、嵌套对象时,子对象不可以是内部类,不然序列化时会栈溢出。
2、每个类需要有默认的构造方法。
2、redisTemplate中的序列化
protostuff有一个特点就是你反序列化的时候需要指定反序列化的类型Class,而如果按常规spring-data-redis规范,只能实现RedisSerializer接口,其中反序列化接口T deserialize(byte[] bytes) throws SerializationException;无法指定Class,所以换个思路,我们在调用redisTemplate操作的时候不是直接放对象而是直接放序列化后的byte[],而反序列化的时候获取byte[]再通过protostuff转为对应的class。注意一点是enableDefaultSerializer这个属性要置为false,并且不要配置valueSerializer因为如果不设置该属性RedisTemplate初始化的时候会指定默认的序列化也就是JdkSerializationRedisSerializer来作为序列化和反序列化。
参考:https://blog.csdn.net/butioy_org/article/details/78412395