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; }