Redis序列化配置

序列化說明

修改RedisTemplate的默認序列化配置,默認是使用JDK的序列化,經過本身實現RedisSerializer接口編寫須要的序列化方式。java

使用Fastjson進行RedisTemplate的Value序列化

package cc.xuepeng.config;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.serializer.SerializerFeature;
import org.springframework.data.redis.serializer.RedisSerializer;

import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;

/**
 * 使用Alibaba的FastJson做爲Json序列化的工具。
 *
 * @param <T>
 * @author xuepeng
 */
public class FastJsonRedisSerializer<T> implements RedisSerializer<T> {

    /**
     * 默認的轉換編碼。
     */
    private static final Charset DEFAULT_CHARSET = Charset.forName(StandardCharsets.UTF_8.name());
    /**
     * 要轉換的類的Class對象。
     */
    private Class<T> clazz;

    /**
     * 構造函數。
     *
     * @param clazz 設置要序列化的對象的Class對象。
     */
    public FastJsonRedisSerializer(Class<T> clazz) {
        super();
        this.clazz = clazz;
    }

    /**
     * 序列化對象。
     *
     * @param object 要被序列化的對象。
     * @return 序列化成字節數組。
     */
    @Override
    public byte[] serialize(T object) {
        if (object == null) {
            return new byte[0];
        }
        return JSON.toJSONString(object, SerializerFeature.WriteClassName).getBytes(DEFAULT_CHARSET);
    }

    /**
     * 反序列化對象。
     *
     * @param bytes 字節數組。
     * @return 要序列化的對象。
     */
    @Override
    public T deserialize(byte[] bytes) {
        if (bytes == null || bytes.length <= 0) {
            return null;
        }
        String str = new String(bytes, DEFAULT_CHARSET);
        return JSON.parseObject(str, clazz);
    }

}

進行RedisTemplate的Key序列化

package cc.xuepeng.config;

import com.alibaba.fastjson.JSON;
import org.springframework.data.redis.serializer.RedisSerializer;
import org.springframework.util.Assert;
import org.springframework.util.StringUtils;

import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;

/**
 * 自定義StringRedisSerializer列化器。
 * 原生的StringRedisSerializer在使用@Cacheable註解時,當key不是String類型會發生錯誤。
 * 由於原生的StringRedisSerializer只支持String。
 *
 * @author xuepeng
 */
public class StringRedisSerializer implements RedisSerializer<Object> {

    /**
     * 默認的轉換編碼。
     */
    private final Charset charset;
    /**
     * 反斜槓符號。
     */
    private static final String TARGET = "\"";
    /**
     * 空格符號。
     */
    private static final String REPLACEMENT = "";

    /**
     * 構造函數。
     */
    public StringRedisSerializer() {
        this(Charset.forName(StandardCharsets.UTF_8.name()));
    }

    /**
     * 構造函數。
     *
     * @param charset 轉換編碼。
     */
    public StringRedisSerializer(Charset charset) {
        Assert.notNull(charset, "Charset must not be null!");
        this.charset = charset;
    }

    @Override
    public byte[] serialize(Object object) {
        String string = JSON.toJSONString(object);
        if (StringUtils.isEmpty(string)) {
            return new byte[0];
        }
        string = string.replace(TARGET, REPLACEMENT);
        return string.getBytes(charset);
    }

    @Override
    public Object deserialize(byte[] bytes) {
        if (bytes != null) {
            return new String(bytes, charset);
        }
        return null;
    }

}

設置RedisConfig

/**
 * Redis配置類。
 *
 * @author xuepeng
 */
@Configuration
@AutoConfigureAfter(RedisAutoConfiguration.class)
public class RedisConfig {

    /**
     * 重寫Redis序列化方式,使用Json方式:
     * 當咱們的數據存儲到Redis的時候,咱們的鍵(key)和值(value)都是經過Spring提供的Serializer序列化到數據庫的。
     * RedisTemplate默認使用的是JdkSerializationRedisSerializer,StringRedisTemplate默認使用的是StringRedisSerializer。
     * 在此咱們將本身配置RedisTemplate並定義Serializer。
     *
     * @param redisConnectionFactory redis鏈接工廠。
     * @return redisTemplate對象。
     */
    @Bean
    public RedisTemplate<String, Object> redisTemplate(LettuceConnectionFactory redisConnectionFactory) {
        RedisTemplate<String, Object> redisTemplate = new RedisTemplate<>();
        redisTemplate.setConnectionFactory(redisConnectionFactory);

        FastJsonRedisSerializer<Object> fastJsonRedisSerializer = new FastJsonRedisSerializer<>(Object.class);
        // 全局開啓AutoType,不建議使用
        // ParserConfig.getGlobalInstance().setAutoTypeSupport(true);
        // 建議使用這種方式,小範圍指定白名單
        ParserConfig.getGlobalInstance().addAccept("cc.xuepeng.");
        // 設置鍵(key)的序列化採用StringRedisSerializer。
        redisTemplate.setKeySerializer(new StringRedisSerializer());
        redisTemplate.setHashKeySerializer(new StringRedisSerializer());
        // 設置值(value)的序列化採用FastJsonRedisSerializer。
        redisTemplate.setValueSerializer(fastJsonRedisSerializer);
        redisTemplate.setHashValueSerializer(fastJsonRedisSerializer);
        return redisTemplate;
    }

}

測試

@RunWith(SpringRunner.class)
@SpringBootTest
public class RedisHelloWorldTest {

    private RedisTemplate<String, Object> redisTemplate;

    @Autowired
    void setRedisTemplate(RedisTemplate<String, Object> redisTemplate) {
        this.redisTemplate = redisTemplate;
    }

    @Test
    public void testGetEntFileById() {
        redisTemplate.opsForValue().set("hello", "world");
        String ret = (String) redisTemplate.opsForValue().get("hello");
        Assert.assertEquals("world", ret);
    }

    @Test
    public void testGetUser() {
        Department department = new Department();
        department.setName("總部");
        User user = new User("jack", 22, LocalDate.now());
        department.getUsers().add(user);
        Department children = new Department();
        children.setName("分部");
        department.getChildren().add(children);

        redisTemplate.opsForHash().put("depts", "01", department);
        redisTemplate.opsForHash().put("depts", "02", department);
        redisTemplate.opsForHash().put("depts", "03", department);
        Department dept1 = (Department) redisTemplate.opsForHash().get("depts", "01");
        System.out.println(dept1);

        Map<Object, Object> map = redisTemplate.opsForHash().entries("depts");
        Department d = (Department) map.get("01");
        System.out.println(d.getName());
    }
}

輸出:redis

Department(name=總部, users=[User(name=jack, age=22, birthday=2019-12-23)], children=[Department(name=分部, users=[], children=[])])
總部
相關文章
相關標籤/搜索