修改Spring Cache Redis的序列化方式为JSON

springboot提供了开箱即用的缓存组件

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-cache</artifactId>
</dependency>

它支持很多缓存,Redis/JCache/Hazelcast…

使用最为广泛的还是Redis,毕竟它支持分布式环境中使用

前提

这里不会去讲太多关于Redis,spring-boot-starter-cache相关的东西。假设你已经掌握了它们。

默认的序列化方式

RedisCacheConfiguration,这个类定义了缓存序列化行为等等参数,默认是使用 RedisSerializer.java,也就是JDK的序列化方式。

这种方式序列化到Redis后,只能由Java再反序列化回来,有一定限制。可以考虑序列化为通用的JSON格式,那么其他的系统/语言也是可以直接读取解析的。

	public static RedisCacheConfiguration defaultCacheConfig(@Nullable ClassLoader classLoader) {

		DefaultFormattingConversionService conversionService = new DefaultFormattingConversionService();

		registerDefaultConverters(conversionService);

		return new RedisCacheConfiguration(Duration.ZERO, true, true, CacheKeyPrefix.simple(),
				SerializationPair.fromSerializer(RedisSerializer.string()),
				SerializationPair.fromSerializer(RedisSerializer.java(classLoader)), conversionService);
	}

自定义配置实现JSON序列化

如果我们不提供RedisCacheConfiguration配置,那么系统就会采用默认的。

import com.alibaba.fastjson.support.spring.GenericFastJsonRedisSerializer;
import org.springframework.boot.autoconfigure.cache.CacheProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.cache.RedisCacheConfiguration;
import org.springframework.data.redis.serializer.RedisSerializationContext;


@Configuration
public class CustomRedisCacheConfiguration {

    @Bean
    public RedisCacheConfiguration redisCacheConfiguration(CacheProperties cacheProperties){

        RedisCacheConfiguration redisCacheConfiguration = RedisCacheConfiguration.defaultCacheConfig();

        // 先载入配置文件中的配置信息
        CacheProperties.Redis redisProperties = cacheProperties.getRedis();
        if (redisProperties.getTimeToLive() != null) {
            redisCacheConfiguration = redisCacheConfiguration.entryTtl(redisProperties.getTimeToLive());
        }
        if (redisProperties.getKeyPrefix() != null) {
            redisCacheConfiguration = redisCacheConfiguration.prefixCacheNameWith(redisProperties.getKeyPrefix());
        }
        if (!redisProperties.isCacheNullValues()) {
            redisCacheConfiguration = redisCacheConfiguration.disableCachingNullValues();
        }
        if (!redisProperties.isUseKeyPrefix()) {
            redisCacheConfiguration = redisCacheConfiguration.disableKeyPrefix();
        }

        // 在最后设置Value的序列化方式
        // 这里使用Fastjson提供的通用序列化器
        redisCacheConfiguration = redisCacheConfiguration.serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(new GenericFastJsonRedisSerializer()));

        return redisCacheConfiguration;
    }
}

不仅仅是Fastjson,Jackson也提供了一个实现:

org.springframework.data.redis.serializer.GenericJackson2JsonRedisSerializer

当然你完全可以自己实现public interface RedisSerializer<T> 接口,完成自己的序列化和反序列化逻辑。

不好的是这种缓存组件不好做局部过期时间控制,要对不同方法设置不同过期时间不好操作

需要针对性设置过期时间的场景,自己实现一个就行。也不是太难。