alibaba.fastjson内部已经提供了对Redis存储对象序列化的工具类GenericFastJsonRedisSerializer,但是该工具在反序列化时返回为Object,我们仿照GenericFastJsonRedisSerializer来自定义一个扩展的工具类,反序列化后自动转化为指定的java对象。
- GenericFastJsonRedisSerializer 源码
package com.alibaba.fastjson.support.spring;import com.alibaba.fastjson.JSON;import com.alibaba.fastjson.parser.ParserConfig;import com.alibaba.fastjson.serializer.SerializerFeature;import com.alibaba.fastjson.util.IOUtils;import org.springframework.data.redis.serializer.RedisSerializer;import org.springframework.data.redis.serializer.SerializationException;/** * {@link RedisSerializer} FastJson Generic Impl * @author lihengming * @since 1.2.36 */public class GenericFastJsonRedisSerializer implements RedisSerializer
- 自定义FastJsonRedisSerializer
import java.nio.charset.Charset;import com.alibaba.fastjson.parser.ParserConfig;import org.springframework.data.redis.serializer.RedisSerializer;import org.springframework.data.redis.serializer.SerializationException;import com.alibaba.fastjson.JSON;import com.alibaba.fastjson.serializer.SerializerFeature;/** *fastjson序列化 * * @author xubin * @version 1.0 * @taskId * @param 泛化 * @CreateDate Nov 8, 2018 */public class FastJsonRedisSerializer implements RedisSerializer { private final static ParserConfig defaultRedisConfig = new ParserConfig(); static { defaultRedisConfig.setAutoTypeSupport(true);} /** * DEFAULT_CHARSET */ public static final Charset DEFAULT_CHARSET = Charset.forName("UTF-8"); /** * clazz 反序列化类 */ private Class clazz; /** * 构造器 * * @param clazz 反序列化目标类 */ public FastJsonRedisSerializer(Class clazz) { super(); this.clazz = clazz; } /** * Description: 序列化 * * @author xubin * @taskId * @param t * @return * @throws SerializationException */ @Override public byte[] serialize(T t) throws SerializationException { if (t == null) { return new byte[0]; } return JSON.toJSONString(t, SerializerFeature.WriteClassName).getBytes(DEFAULT_CHARSET); } /** * Description: 反序列化 * * @author xubin * @taskId * @param bytes * @return * @throws SerializationException */ @Override public T deserialize(byte[] bytes) throws SerializationException { if (bytes == null || bytes.length <= 0) { return null; } String str = new String(bytes, DEFAULT_CHARSET); return (T) JSON.parseObject(str, clazz, defaultRedisConfig); }}
- json报文示例
{ "@type": "com.lucas.device.mqtt.protocol.MqttPacketCache", "id": 647682641483370500, "packet": { "@type": "com.lucas.device.mqtt.protocol.Packet", "body": { "@type": "com.lucas.device.mqtt.protocol.payload.BindFacesetBody", "facesetTokenList": [ "630281772974575616" ] }, "head": { "code": 114, "id": 647682641483370500, "type": 2, "version": 1 } }}
此处要注意的是defaultRedisConfig.setAutoTypeSupport(true)这段,在调用JSON.toJSONString(object, SerializerFeature.WriteClassName)时会在json报文中包含@type信息,反序列化时会根据 对要映射的对象进行检查,所以请确保要反序列化的类型有默认构造器同时序列化工具打开了autoType的支持,否则反序列化会出现异常com.alibaba.fastjson.JSONException: autoType is not support。
- RedisConfig 配置自定义的序列化工具类
/** * Description: * * @author xubin * @taskId * @param factory 工厂对象 * @return */ @Bean public RedisTemplatepacketRedisTemplate(RedisConnectionFactory factory) { RedisTemplate redisTemplate = new RedisTemplate<>(); StringRedisSerializer stringSerializer = new StringRedisSerializer(); redisTemplate.setConnectionFactory(factory); redisTemplate.setKeySerializer(stringSerializer); redisTemplate.setValueSerializer(new FastJsonRedisSerializer<>(MqttPacketCache.class)); redisTemplate.setHashKeySerializer(stringSerializer); redisTemplate.setHashValueSerializer(new FastJsonRedisSerializer<>(MqttPacketCache.class)); return redisTemplate; }