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