alibaba.fastjson内部已经提供了对Redis存储对象序列化的工具类GenericFastJsonRedisSerializer,可是该工具在反序列化时返回为Object,咱们仿照GenericFastJsonRedisSerializer来自定义一个扩展的工具类,反序列化后自动转化为指定的java对象。java
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<Object> { private final static ParserConfig defaultRedisConfig = new ParserConfig(); static { defaultRedisConfig.setAutoTypeSupport(true);} public byte[] serialize(Object object) throws SerializationException { if (object == null) { return new byte[0]; } try { return JSON.toJSONBytes(object, SerializerFeature.WriteClassName); } catch (Exception ex) { throw new SerializationException("Could not serialize: " + ex.getMessage(), ex); } } public Object deserialize(byte[] bytes) throws SerializationException { if (bytes == null || bytes.length == 0) { return null; } try { return JSON.parseObject(new String(bytes, IOUtils.UTF8), Object.class, defaultRedisConfig); } catch (Exception ex) { throw new SerializationException("Could not deserialize: " + ex.getMessage(), ex); } } }
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; /** * <Description> fastjson序列化<br> * * @author xubin<br> * @version 1.0<br> * @taskId <br> * @param <T> 泛化 * @CreateDate Nov 8, 2018 <br> */ public class FastJsonRedisSerializer<T> implements RedisSerializer<T> { private final static ParserConfig defaultRedisConfig = new ParserConfig(); static { defaultRedisConfig.setAutoTypeSupport(true);} /** * DEFAULT_CHARSET <br> */ public static final Charset DEFAULT_CHARSET = Charset.forName("UTF-8"); /** * clazz 反序列化类<br> */ private Class<T> clazz; /** * <Description> 构造器<br> * * @param clazz 反序列化目标类 */ public FastJsonRedisSerializer(Class<T> clazz) { super(); this.clazz = clazz; } /** * Description: 序列化<br> * * @author xubin<br> * @taskId <br> * @param t * @return * @throws SerializationException <br> */ @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: 反序列化<br> * * @author xubin<br> * @taskId <br> * @param bytes * @return * @throws SerializationException <br> */ @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); } }
{ "@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信息,反序列化时会根据 @type 对要映射的对象进行检查,因此请确保要反序列化的类型有默认构造器同时序列化工具打开了autoType的支持,不然反序列化会出现异常com.alibaba.fastjson.JSONException: autoType is not support。redis
/** * Description: <br> * * @author xubin<br> * @taskId <br> * @param factory 工厂对象 * @return <br> */ @Bean public RedisTemplate<String, MqttPacketCache> packetRedisTemplate(RedisConnectionFactory factory) { RedisTemplate<String, MqttPacketCache> 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; }