為Redis配置自定義fastJson序列化工具類
阿新 • • 發佈:2019-05-22
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<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); } } }
- 自定義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; /** * <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); } }
- 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資訊,反序列化時會根據 @type 對要對映的物件進行檢查,所以請確保要反序列化的型別有預設構造器同時序列化工具打開了autoType的支援,否則反序列化會出現異常com.alibaba.fastjson.JSONException: autoType is not support。
- RedisConfig 配置自定義的序列化工具類
/**
* 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 redisTempl