1. 程式人生 > >為Redis配置自定義fastJson序列化工具類

為Redis配置自定義fastJson序列化工具類

    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