SpringBoot配置redis使用fastJson进行序列化

6,481 阅读2分钟

这里使用的SpringBoot版本为:2.3.0.RELEASE,默认使用的redis连接为方式为lettuce,所以还需要导入以下依赖

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<dependency>
    <groupId>org.apache.commons</groupId>
    <artifactId>commons-pool2</artifactId>
</dependency>

1.首先配置redis信息,在application.yml中配置

spring: 
  redis:
    host: 127.0.0.1
    password:
    port: 6379
    database: 0
    # 连接超时时间(毫秒)
    timeout: 10s
    lettuce:
      # 关闭超时时间
      shutdown-timeout: 1s
      pool:
        # 连接池最大连接数(使用负值表示没有限制) 默认 8
        max-active: 1000
        # 连接池中的最大空闲连接 默认 8
        max-idle: 300
        # 连接池中的最小空闲连接 默认 0
        min-idle: 3
        # 连接池最大阻塞等待时间(使用负值表示没有限制) 默认 -1
        max-wait: 1s

2.使用fastJSON作为redis的序列化方式,导入fastJson依赖

<dependency>
    <groupId>com.alibaba</groupId>
    <artifactId>fastjson</artifactId>
    <version>1.2.38</version>
</dependency>

2.1 新建RedisConfig类配置redis信息

package com.avatar.redis;

import com.alibaba.fastjson.parser.ParserConfig;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.cache.RedisCacheConfiguration;
import org.springframework.data.redis.cache.RedisCacheManager;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.RedisSerializationContext;

import java.time.Duration;

/**
 * com.avatar.redis
 * Description: 设置redis配置
 *
 * @author jack
 * @date 2020/11/22 14:36
 */
@Configuration
public class RedisConfig {

    @Bean
    public LettuceConnectionFactory redisConnectionFactory() {
        return new LettuceConnectionFactory();
    }

    @Bean
    public RedisCacheManager cacheManager(RedisConnectionFactory connectionFactory) {
        FastJsonRedisSerializer<Object> fastJsonRedisSerializer = new FastJsonRedisSerializer<>(Object.class);
        StringRedisSerializer stringRedisSerializer = new StringRedisSerializer();
        RedisCacheConfiguration config = RedisCacheConfiguration.defaultCacheConfig()
                // 默认缓存时间
                .entryTtl(Duration.ofSeconds(600))
                // 设置key的序列化方式
                .serializeKeysWith(RedisSerializationContext.SerializationPair.fromSerializer(stringRedisSerializer))
                // 设置value的序列化方式
                .serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(fastJsonRedisSerializer));
        RedisCacheManager redisCacheManager = RedisCacheManager.builder(connectionFactory)
                .cacheDefaults(config)
                .transactionAware()
                .build();
        return redisCacheManager;
    }

    @Bean
    public RedisTemplate<Object, Object> redisTemplate(RedisConnectionFactory redisConnectionFactory) {
        RedisTemplate<Object, Object> redisTemplate = new RedisTemplate<>();
        // 使用fastJson序列化
        FastJsonRedisSerializer fastJsonRedisSerializer = new FastJsonRedisSerializer(Object.class);
        // value值的序列化采用fastJsonRedisSerializer
        redisTemplate.setValueSerializer(fastJsonRedisSerializer);
        redisTemplate.setHashValueSerializer(fastJsonRedisSerializer);
        // 全局开启AutoType,不建议使用
        // ParserConfig.getGlobalInstance().setAutoTypeSupport(true);
        // 建议使用这种方式,小范围指定白名单,需要序列化的类
        ParserConfig.getGlobalInstance().addAccept("com.avatar");
        // key的序列化采用StringRedisSerializer
        redisTemplate.setKeySerializer(new StringRedisSerializer());
        redisTemplate.setHashKeySerializer(new StringRedisSerializer());
        redisTemplate.setConnectionFactory(redisConnectionFactory);
        return redisTemplate;
    }

}

2.2 新建FastJsonRedisSerializer(redis value序列化格式)

package com.avatar.redis;

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

import java.nio.charset.Charset;

/**
 * com.avatar.redis
 * Description: 设置redis使用fastJson序列化
 *
 * @author jack
 * @date 2020/11/22 14:36
 */
public class FastJsonRedisSerializer<T> implements RedisSerializer<T> {

    public static final Charset DEFAULT_CHARSET = Charset.forName("UTF-8");

    private Class<T> clazz;

    public FastJsonRedisSerializer(Class<T> clazz) {
        super();
        this.clazz = clazz;
    }

    @Override
    public byte[] serialize(T t) throws SerializationException {
        if (t == null) {
            return new byte[0];
        }
        // byte[] bytes = JSON.toJSONString(t, SerializerFeature.WriteClassName, ).getBytes(DEFAULT_CHARSET);
        byte[] bytes = JSON.toJSONString(t, SerializerFeature.WriteClassName,
                // 是否输出值为null的字段,默认为false
                SerializerFeature.WriteMapNullValue,
                // List字段如果为null,输出为[],而非null
                SerializerFeature.WriteNullListAsEmpty).getBytes(DEFAULT_CHARSET);
        return bytes;
    }

    @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);
    }
}

2.3 新建StringRedisSerializer(redis key序列化格式)

package com.avatar.redis;

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

import java.nio.charset.Charset;

/**
 * com.avatar.redis
 * Description: 重写序列化
 *
 * @author jack
 * @date 2020/11/22 14:36
 */
public class StringRedisSerializer<T> implements RedisSerializer<Object> {

    private final Charset charset;

    private final String target = "\"";

    private final String replacement = "";

    public StringRedisSerializer() {
        this(Charset.forName("UTF8"));
    }

    public StringRedisSerializer(Charset charset) {
        Assert.notNull(charset, "Charset must not be null!");
        this.charset = charset;
    }

    @Override
    public byte[] serialize(Object object) throws SerializationException {
        String string = JSON.toJSONString(object);
        if (string == null) {
            return null;
        }
        string = string.replace(target, replacement);
        return string.getBytes(charset);
    }

    @Override
    public Object deserialize(byte[] bytes) throws SerializationException {
        return (bytes == null ? null : new String(bytes, charset));
    }
}

3.进行测试

使用redisTemplate存储redis信息

package com.avatar.redis;

import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.RandomUtil;
import com.avatar.model.User;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.data.redis.core.RedisTemplate;

import java.util.Date;

/**
 * com.avatar.redis
 * Description:
 *
 * @author jack
 * @date 2020/11/22 15:01
 */
@SpringBootTest
public class RedisTest {

    @Autowired
    private RedisTemplate<Object, Object> redisTemplate;

    @Test
    public void setValue() {
        redisTemplate.opsForValue().set("avatar:message-service:token", RandomUtil.randomNumbers(10));
    }

    @Test
    public void setEntity() {
        User user = new User();
        user.setUserName("张三");
        user.setPassword(IdUtil.randomUUID());
        user.setBirthday(new Date());
        user.setPhoneNumber("12345676543");
        user.setAge(23);
        redisTemplate.opsForValue().set("avatar:message-service:user", user);
        System.out.println("保存成功");
        User printUser = (User) redisTemplate.opsForValue().get("avatar:message-service:user");
        System.out.println("从redis中获取值:" + printUser);
    }

}

测试结果如下: