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=[])])
总部
相关文章
相关标签/搜索