YeBin`s Blog

vuePress-theme-reco YeBin    2017 - 2020
YeBin`s Blog YeBin`s Blog

Choose mode

  • dark
  • auto
  • light
首页
分类
  • java
标签
时间线
联系我
  • GitHub
author-avatar

YeBin

5

Article

2

Tag

首页
分类
  • java
标签
时间线
联系我
  • GitHub
  • Spring整合Redis做缓存

    • /blogs/java/2017/Spring%E6%95%B4%E5%90%88Redis%E5%81%9A%E7%BC%93%E5%AD%98.html#
      • 一、准备相关Jar包
      • 二、Redis相关配置
      • 三、配置redisTemplate和序列化器
      • 四、开启缓存注解
      • 五、总结

Spring整合Redis做缓存

vuePress-theme-reco YeBin    2017 - 2020

Spring整合Redis做缓存


YeBin 2017-12-25 tag1

#

# 一、准备相关Jar包

​ 我这里使用的是Spring-data-redis 2.x,如果你使用的是1.x版本的话,配置会有点不同

 <dependency>
            <groupId>org.springframework.data</groupId>
            <artifactId>spring-data-redis</artifactId>
            <version>2.1.5.RELEASE</version>
 </dependency>
 <dependency>
            <groupId>redis.clients</groupId>
            <artifactId>jedis</artifactId>
            <version>2.9.0</version>
 </dependency>
1
2
3
4
5
6
7
8
9
10

# 二、Redis相关配置

使用XML方式配置


    <context:property-placeholder location="classpath:redis.properties" ignore-unresolvable="true"/>

    <bean id="poolConfig" class="redis.clients.jedis.JedisPoolConfig">
        <property name="maxTotal" value="${redis.maxTotal}"/>
        <property name="maxIdle" value="${redis.maxIdle}"/>
        <property name="maxWaitMillis" value="${redis.maxWaitMillis}"/>
    </bean>


    <!--Spring-data-redis 2.0以上配置-->

    <bean id="redisPassword" class="org.springframework.data.redis.connection.RedisPassword">
        <constructor-arg  index="0" value="${redis.password}"></constructor-arg>
    </bean>


    <!--Spring-data-redis 2.0以上配置-->
    <bean id="redisStandaloneConfiguration" class="org.springframework.data.redis.connection.RedisStandaloneConfiguration">
        <property name="hostName" value="${redis.host}"/>
        <property name="port" value="${redis.port}"/>
        <property name="password" ref="redisPassword" />
        <property name="database" value="${redis.index}"/>
    </bean>


    <!--Spring-data-redis 2.0以上配置-->
    <bean id="connectionFactory" class="org.springframework.data.redis.connection.jedis.JedisConnectionFactory">
        <constructor-arg  name="standaloneConfig" ref="redisStandaloneConfiguration"/>
    </bean>

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31

# 三、配置redisTemplate和序列化器

Spring向我们提供了一个Cache接口,和CacheManager接口,我们要使用Spring-Cache只要实现这两个接口即可,但 redis给我们提供了一个实现

org.springframework.data.redis.cache.RedisCache以及org.springframework.data.redis.cache.RedisCacheManager
1

如果像自己实现就去实现Cache接口,以及CacheManager接口,前者是用来做缓存逻辑,后者是来管理缓存,不过我这里就使用Redis提供的

 <bean id="redisTemplate" class="org.springframework.data.redis.core.RedisTemplate">
        <property name="connectionFactory" ref="connectionFactory"></property>
        <!-- 对于中文的存储 需要进行序列化操作存储  序列化器  -->
        <property name="keySerializer">
            <bean class="org.springframework.data.redis.serializer.StringRedisSerializer">
            </bean>
        </property>
        <property name="valueSerializer">
            <bean id="jsonRedisSerializer" 			 class="org.springframework.data.redis.serializer.GenericJackson2JsonRedisSerializer">
            <!-- 使用默认的 ObjectMapper,移除JSON格式化后的 “@Class”节点 -->
            <constructor-arg name="mapper">
                <bean class="com.fasterxml.jackson.databind.ObjectMapper"/>
            </constructor-arg>
        </bean>
        </property>
    </bean>


 <bean  id="cacheManager" class="org.springframework.data.redis.cache.RedisCacheManager" >

        <constructor-arg index="0" >
            <bean class="org.springframework.data.redis.cache.DefaultRedisCacheWriter">
                <constructor-arg ref="connectionFactory"/>
            </bean>
        </constructor-arg>
        <constructor-arg index="1">
            <bean class="org.springframework.data.redis.cache.RedisCacheConfiguration" factory-method="defaultCacheConfig" >

            </bean>
        </constructor-arg>

    </bean>

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33

# 四、开启缓存注解

    <!--开启缓存注解 Spring的缓存注解-->

      <cache:annotation-driven    />
1
2
3

​ 然后再要做缓存的Service上贴上缓存注解 就大功告成了

    @Cacheable(cacheNames = "phone:listAll",key = "'phone:'+#start")
    public PageInfo<Phone> listAll(Integer start ,Integer pageSize) {
        PageHelper.startPage(start,pageSize);
        List<Phone> phones = phoneMapper.listAll();
        PageInfo<Phone> pageInfo = new PageInfo<>(phones);
        return  pageInfo;
    }
1
2
3
4
5
6
7

缓存的数据就保存到Redis中了,再次查询的时候就直接从redis中拿出来。

# 五、总结

​ 上面可以看出随便把缓存的数据存入了redis中,但并不是我们预期的结果,因为我再前面设置的是Json格式的序列化器,这里用的却是默认的JDK的序列化器,我找了很多资料,自己也折腾了半天,后来才找打问题的所在

@Bean
    public RedisCacheManager redisCacheManager(RedisConnectionFactory factory)
    {
        RedisCacheWriter redisCacheWriter=RedisCacheWriter.lockingRedisCacheWriter(factory);
        /* 使用 json 序列化 */
        //不做这个配置Json序列化器将不能生效
        RedisSerializer<Object> jsonSerializer = new GenericJackson2JsonRedisSerializer();
        RedisSerializationContext.SerializationPair<Object> serializationPair = RedisSerializationContext.SerializationPair.fromSerializer(jsonSerializer);
        RedisCacheConfiguration defaultCacheConfig = RedisCacheConfiguration.defaultCacheConfig().serializeValuesWith(serializationPair);

        /* 设置保存时间*/
        defaultCacheConfig.entryTtl(Duration.ofHours(8));
        return new RedisCacheManager(redisCacheWriter, defaultCacheConfig);


    }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16

​ 我使用Java Congfig的方式注入了一个CacheManager,再此尝试后:

数据以json各是保存起来了,我分析了很久,对比XML和JavaConfig的方式,找出了原因:我再使用XML方式配置CacheManager的时候,没有没有给它设置serializerPair,这才导致之前设置的json序列化器没生效:

public RedisCacheManager(RedisCacheWriter cacheWriter, RedisCacheConfiguration defaultCacheConfiguration) {
        this(cacheWriter, defaultCacheConfiguration, true);
    }

redisCacheManager需要有连个参数的构造函数,cacheWriter和RedisCacheConfigruation
而RedisCacheConfigruation 需要给它设置一个alueSerializationPair,否者就会使用默认的jdk序列化器
    public RedisCacheConfiguration serializeValuesWith(SerializationPair<?> valueSerializationPair) {
        Assert.notNull(valueSerializationPair, "ValueSerializationPair must not be null!");
        return new RedisCacheConfiguration(this.ttl, this.cacheNullValues, this.usePrefix, 	     this.keyPrefix, this.keySerializationPair, valueSerializationPair, this.conversionService);
    }
1
2
3
4
5
6
7
8
9
10