学科分类
目录
Spring Boot开发

自定义RedisTemplate

1.Redis API默认序列化机制

基于Redis API的Redis缓存实现是使用RedisTemplate模板进行数据缓存操作的,这里打开RedisTemplate类,查看该类的源码信息,示例代码如下。

public class RedisTemplate<K, V> extends RedisAccessor 
                                 implements RedisOperations<K, V>, BeanClassLoaderAware {
    // 声明了key、value的各种序列化方式,初始值为空
    @Nullable
    private RedisSerializer keySerializer = null;
    @Nullable
    private RedisSerializer valueSerializer = null;
    @Nullable
    private RedisSerializer hashKeySerializer = null;
    @Nullable
    private RedisSerializer hashValueSerializer = null;
    ...
    // 进行默认序列化方式设置,设置为JDK序列化方式
    public void afterPropertiesSet() {
        super.afterPropertiesSet();
        boolean defaultUsed = false;
        if(this.defaultSerializer == null) {
            this.defaultSerializer = new JdkSerializationRedisSerializer(
           this.classLoader != null?this.classLoader:this.getClass().getClassLoader());
        }
        ...
    }
    ...
}

从上述RedisTemplate核心源码可以看出,在RedisTemplate内部声明了缓存数据key、value的各种序列化方式,且初始值都为空;在afterPropertiesSet()方法中,判断如果默认序列化参数defaultSerializer为空,将数据的默认序列化方式设置为JdkSerializationRedisSerializer。

根据上述源码信息的分析,可以得到以下两个重要的结论。

(1)使用RedisTemplate进行Redis数据缓存操作时,内部默认使用的是JdkSerializationRedisSerializer序列化方式,所以进行数据缓存的实体类必须实现JDK自带的序列化接口(例如Serializable);

(2)使用RedisTemplate进行Redis数据缓存操作时,如果自定义了缓存序列化方式defaultSerializer,那么将使用自定义的序列化方式。

另外,在RedisTemplate类源码中,看到的缓存数据key、value的各种序列化类型都是RedisSerializer。进入RedisSerializer源码查看RedisSerializer支持的序列化方式(进入该类后,使用Ctrl+Alt+左键单击类名查看),具体如图1所示。

图1 RedisSerializer接口实现

从图1可以看出,RedisSerializer是一个Redis序列化接口,默认有6个实现类,这6个实现类代表了6种不同的数据序列化方式。其中,JdkSerializationRedisSerializer是JDK自带的,也是RedisTemplate内部默认使用的数据序列化方式,开发者可以根据需要选择其他支持的序列化方式(例如JSON方式)。

2.自定义RedisTemplate序列化机制

在项目中引入Redis依赖后,Spring Boot提供的RedisAutoConfiguration自动配置会生效。打开RedisAutoConfiguration类,查看内部源码中关于RedisTemplate的定义方式,核心代码如下所示。

public class RedisAutoConfiguration {
    @Bean
    @ConditionalOnMissingBean(
        name = {"redisTemplate"}
    )
    public RedisTemplate<Object, Object> redisTemplate(RedisConnectionFactory 
                                     redisConnectionFactory) throws UnknownHostException {
        RedisTemplate<Object, Object> template = new RedisTemplate();
        template.setConnectionFactory(redisConnectionFactory);
        return template;
    }
    ...
}

从上述RedisAutoConfiguration核心源码中可以看出,在Redis自动配置类中,通过Redis连接工厂RedisConnectionFactory初始化了一个RedisTemplate;该类上方添加了@ConditionalOnMissingBean注解(顾名思义,当某个Bean不存在时生效),用来表明如果开发者自定义了一个名为redisTemplate的Bean,则该默认初始化的RedisTemplate会被覆盖。

如果想要使用自定义序列化方式的RedisTemplate进行数据缓存操作,可以参考上述核心代码创建一个名为redisTemplate的Bean组件,并在该组件中设置对应的序列化方式即可。

接下来,在chapter06项目中创建名为com.itheima.config的包,在该包下创建一个Redis自定义配置类RedisConfig,并按照上述思路自定义名为redisTemplate的Bean组件,内容如文件1所示。

文件1 RedisConfig.java

 1    import com.fasterxml.jackson.annotation.*;
 1    import com.fasterxml.jackson.databind.ObjectMapper;
 2    import org.springframework.context.annotation.*;
 3    import org.springframework.data.redis.connection.RedisConnectionFactory;
 4    import org.springframework.data.redis.core.RedisTemplate;
 5    import org.springframework.data.redis.serializer.*;
 6    @Configuration   // 定义一个配置类
 7    public class RedisConfig {
 8        @Bean
 9        public RedisTemplate<Object, Object> redisTemplate(RedisConnectionFactory
 10                                                                      redisConnectionFactory) {
 11            RedisTemplate<Object, Object> template = new RedisTemplate();
 12            template.setConnectionFactory(redisConnectionFactory);
 13            // 使用JSON格式序列化对象,对缓存数据key和value进行转换
 14            Jackson2JsonRedisSerializer jacksonSeial = 
 15                                              new Jackson2JsonRedisSerializer(Object.class);
 16            // 解决查询缓存转换异常的问题
 17            ObjectMapper om = new ObjectMapper();
 18            om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
 19            om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
 20            jacksonSeial.setObjectMapper(om);
 21            // 设置RedisTemplate模板API的序列化方式为JSON
 22            template.setDefaultSerializer(jacksonSeial);
 23            return template;
 24        }
 25    }

文件1中,通过@Configuration注解定义了一个RedisConfig配置类,并使用@Bean注解注入了一个默认名称为方法名的redisTemplate组件(注意,该Bean组件名称必须是redisTemplate)。在定义的Bean组件中,自定义了一个RedisTemplate,使用自定义的Jackson2JsonRedisSerializer数据序列化方式;在定制序列化方式中,定义了一个ObjectMapper用于进行数据转换设置。

3.效果测试

启动chapter06项目,项目启动成功后,通过浏览器访问“http://localhost:8080/api/get/3”查询id为3的用户评论信息,并重复刷新浏览器查看同一条数据信息,结果如图2所示。

图2 findById()方法查询结果

查看控制台打印的SQL查询语句,结果如图3所示。

图3 执行findById()方法控制台显示的SQL语句

从图2和3可以看出,执行findById()方法正确查询出用户评论信息Comment,重复进行同样的查询操作,数据库只执行了一次SQL语句,这说明定制的Redis缓存生效。

使用Redis客户端可视化管理工具Redis Desktop Manager查看缓存数据,效果如图4所示。

图4 Redis数据库可视化展示

从图4可以看出,执行findById()方法查询出用户评论信息Comment正确存储到了Redis缓存库中,且缓存到Redis服务的数据已经使用了JSON格式存储展示,查看和管理也非常方便,说明自定义的Redis API模板工具RedisTemplate生效。

点击此处
隐藏目录