【redis】3.Spring 集成注解 redis 項目配置使用


spring-data-redis  項目,配合 spring 特性並集成 Jedis 的一些命令和方法。

配置redis繼承到spring管理項目,使用注解實現redis緩存功能。

參考:http://www.cnblogs.com/java-class/p/7112541.html

 

步驟:1.maven的pom.xml文件導入架包

   2.配置文件添加配置

   3.spring管理bean的生成,xml文件配置

   4. RedisCacheConfig redis自定義的工具類,自定義redis的key生成規則

   5.在你想要做緩存的地方,使用注解進行緩存

 

 

1.maven的pom.xml文件導入架包【本來spring-data-redis架包版本使用最新的2.0.0 ,甚至使用到1.8.4版本,只要保存,啟動項目,spring管理的bean都會創建失敗,架包沖突的緣故或者其他問題,所以退而求其次,使用1.6.2版本】

<!-- redis架包 -->
          <dependency>
            <groupId>org.springframework.data</groupId>
            <artifactId>spring-data-redis</artifactId>
            <version>1.6.2.RELEASE</version>
          </dependency>
        <dependency>
            <groupId>redis.clients</groupId>
            <artifactId>jedis</artifactId>
            <version>2.9.0</version>
        </dependency>

 

2.配置文件添加配置

#============================#
#==== Redis settings ====#
#============================#
#redis 服務器 IP
redis.host=127.0.0.1

#redis 服務器端口
redis.port=6379

#redis 密碼
redis.pass=398023

#redis 支持16個數據庫(相當於不同用戶)可以使不同的應用程序數據彼此分開同時又存儲在相同的實例上
redis.dbIndex=0

#redis 緩存數據過期時間單位秒
redis.expiration=3000

#控制一個 pool 最多有多少個狀態為 idle 的jedis實例
redis.maxIdle=300

#控制一個 pool 可分配多少個jedis實例
redis.maxActive=600

#當borrow一個jedis實例時,最大的等待時間,如果超過等待時間,則直接拋出JedisConnectionException;
redis.maxWait=1000

#在borrow一個jedis實例時,是否提前進行alidate操作;如果為true,則得到的jedis實例均是可用的;
redis.testOnBorrow=true

 

3.spring管理bean的生成,xml文件配置

 
    <!-- **************************************************redis********************************************************** -->
    <!-- 配置 JedisPoolConfig 實例 -->
    <bean id="poolConfig" class="redis.clients.jedis.JedisPoolConfig">
        <property name="maxIdle" value="${redis.maxIdle}"/>
        <property name="maxTotal" value="${redis.maxActive}"/>
        <property name="maxWaitMillis" value="${redis.maxWait}"/>
        <property name="testOnBorrow" value="${redis.testOnBorrow}"/>
    </bean>

    <!-- 配置JedisConnectionFactory -->
    <bean id="jedisConnectionFactory" class="org.springframework.data.redis.connection.jedis.JedisConnectionFactory">
        <property name="hostName" value="${redis.host}"/>
        <property name="port" value="${redis.port}"/>
        <property name="password" value="${redis.pass}"/>
        <property name="database" value="${redis.dbIndex}"/>
        <property name="poolConfig" ref="poolConfig"/>
    </bean>

    <!-- 配置RedisTemplate -->
    <bean id="redisTemplate" class="org.springframework.data.redis.core.RedisTemplate">
        <property name="connectionFactory" ref="jedisConnectionFactory"/>
    </bean>

    <!-- 配置RedisCacheManager -->
    <bean id="redisCacheManager" class="org.springframework.data.redis.cache.RedisCacheManager">
        <constructor-arg name="redisOperations" ref="redisTemplate"/>
        <property name="defaultExpiration" value="${redis.expiration}"/>
    </bean>

    <!-- 配置RedisCacheConfig -->
    <bean id="redisCacheConfig" class="com.sxd.util.RedisCacheConfig">
        <constructor-arg ref="jedisConnectionFactory"/>
        <constructor-arg ref="redisTemplate"/>
        <constructor-arg ref="redisCacheManager"/>
    </bean>

JedisPoolConfig           jedis連接池配置對象

JedisConnectionFactory         jedis連接工廠,生成連接對象

RedisTemplate          RedisTemplate 對 RedisConnection 進行了封裝。提供連接管理,序列化等功能,它對 Redis 的交互進行了更高層次的抽象,極大的方便和簡化了 Redis 的操作

RedisCacheManager        做為 redis 統一的調度和管理者

RedisCacheConfig         RedisCacheConfig extends org.springframework.cache.annotation.CachingConfigurerSupport,自定義redis的key生成規則,如果不在注解參數中注明key=“”的話,就采用這個類中的key生成規則生成key

 

4. RedisCacheConfig redis自定義的工具類,自定義redis的key生成規則

package com.sxd.util;

import java.lang.reflect.Method;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.cache.CacheManager;
import org.springframework.cache.annotation.CachingConfigurerSupport;
import org.springframework.cache.annotation.EnableCaching;
import org.springframework.cache.interceptor.KeyGenerator;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.cache.RedisCacheManager;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.connection.jedis.JedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;

@Configuration
@EnableCaching
public class RedisCacheConfig extends CachingConfigurerSupport {
     protected final static Logger log = LoggerFactory.getLogger(RedisCacheConfig.class);

        private volatile JedisConnectionFactory mJedisConnectionFactory;
        private volatile RedisTemplate<String, String> mRedisTemplate;
        private volatile RedisCacheManager mRedisCacheManager;

        public RedisCacheConfig() {
            super();
        }

        public RedisCacheConfig(JedisConnectionFactory mJedisConnectionFactory, RedisTemplate<String, String> mRedisTemplate, RedisCacheManager mRedisCacheManager) {
            super();
            this.mJedisConnectionFactory = mJedisConnectionFactory;
            this.mRedisTemplate = mRedisTemplate;
            this.mRedisCacheManager = mRedisCacheManager;
        }

        public JedisConnectionFactory redisConnectionFactory() {
            return mJedisConnectionFactory;
        }

        public RedisTemplate<String, String> redisTemplate(RedisConnectionFactory cf) {
            return mRedisTemplate;
        }

        public CacheManager cacheManager(RedisTemplate<?, ?> redisTemplate) {
            return mRedisCacheManager;
        }

        
        
        @Bean
        public KeyGenerator keyGenerator() {
            return new KeyGenerator() {
                @Override
                public Object generate(Object target, Method method,
                        Object... params) {
                    //規定  本類名+方法名+參數名 為key
                    StringBuilder sb = new StringBuilder();
                    sb.append(target.getClass().getName()+"_");
                    sb.append(method.getName()+"_");
                    for (Object obj : params) {
                        sb.append(obj.toString()+",");
                    }
                    return sb.toString();
                }
            };
        }
        
}

 

 

5.在你想要做緩存的地方,使用注解進行緩存

先介紹幾個注解

  1》@CacheConfig  配置在類上,cacheNames即定義了本類中所有用到緩存的地方,都去找這個庫。只要使用了這個注解,在方法上@Cacheable    @CachePut   @CacheEvict就可以不用寫value去找具體庫名了。【一般不怎么用】

  2》@Cacheable  配置在方法或類上,作用:本方法執行后,先去緩存看有沒有數據,如果沒有,從數據庫中查找出來,給緩存中存一份,返回結果,下次本方法執行,在緩存未過期情況下,先在緩存中查找,有的話直接返回,沒有的話從數據庫查找

  3》@CachePut   類似於更新操作,即每次不管緩存中有沒有結果,都從數據庫查找結果,並將結果更新到緩存,並返回結果

  4》@CacheEvict 用來清除用在本方法或者類上的緩存數據(用在哪里清除哪里)

例子:

最直觀的表現:首次登錄,會有一條數據庫的查詢語句在控制台。

       退出再登錄,不會執行數據庫的查詢,直接從數據庫中取出緩存,登錄成功。

說明:

  ①使用了@Cacheable(value="myUser"),即表示緩存中有,直接從緩存取出,沒有的話先從數據庫中查出,然后再插入

  ②如果未在類上使用@CacheConfig注解規定數據要緩存到哪個庫中,就必須給value一個值,規定數據最后緩存到哪個redis庫中

  ③因為redis緩存數據實際就是鍵值對的形式存儲,因此必須給定key-value的key,這里沒有給key參數賦值,所以key的生成規則按照上面工具類中規定的key生成的

  ④key-value的value就是本方法的返回值,如果要緩存登錄用戶信息,本方法需要進行修改,返回user對象就可以緩存到key-value的value中

 

*******************************************************************************************************************************************************************

*******************************************************************************************************************************************************************

查看一下本次緩存的數據,在redis可視化工具中

myUser是上面注解中的value,也就是緩存數據庫名字叫myUser

鍵名key為:\xAC\xED\x00\x05t\x00Jcom.sxd.controller.WelcomeController_welcome_com.sxd.entity.User@36e69d03,

鍵值對value值:\xAC\xED\x00\x05t\x00\x07success

   ①redis以鍵值對的形式存儲緩存數據,而且會對對象進行序列化,如上圖可以看到,鍵和值前面都有一串序列化的字符

   ② RedisTemplate默認采用的是JDK的序列化策略,保存的key和value都是采用此策略序列化保存的。JdkSerializationRedisSerializer

   ③SDR默認采用的序列化策略有兩種,一種是String的序列化策略,一種是JDK的序列化策略。

        StringRedisTemplate默認采用的是String的序列化策略,保存的key和value都是采用此策略序列化保存的。StringRedisSerializer

        RedisTemplate默認采用的是JDK的序列化策略,保存的key和value都是采用此策略序列化保存的。JdkSerializationRedisSerializer

   就是因為序列化策略的不同,即使是同一個key用不同的Template去序列化,結果是不同的。所以根據key去刪除數據的時候就出現了刪除失敗的問題。

   ④在上面配置文件中,沒有顯式的給出序列化策略,會有默認的序列化策略。

   ⑤如果因為序列化策略不同,可以區顯式的設置  具體可參考:http://blog.csdn.net/y666666y/article/details/70212767

<!-- redis 序列化策略 ,通常情況下key值采用String序列化策略, -->  
<!-- 如果不指定序列化策略,StringRedisTemplate的key和value都將采用String序列化策略; -->  
<!-- 但是RedisTemplate的key和value都將采用JDK序列化 這樣就會出現采用不同template保存的數據不能用同一個template刪除的問題 -->  
<bean id="stringRedisSerializer"   
    class="org.springframework.data.redis.serializer.StringRedisSerializer" />  
  
<bean id='redisWriteTemplate' class="org.springframework.data.redis.core.RedisTemplate">  
    <property name="connectionFactory" ref="jedisWriteConnectionFactory" />  
    <property name="keySerializer" ref="stringRedisSerializer" />  
    <property name="hashKeySerializer" ref="stringRedisSerializer" />  
</bean>

   

 

*************************************************************************************************************************************************************************************

*************************************************************************************************************************************************************************************

最后給出這幾個注解的具體參數以及使用相關配圖參考。

參考自:http://blog.csdn.net/sanjay_f/article/details/47372967

 

表 1. @Cacheable 作用和配置方法

@Cacheable 的作用 主要針對方法配置,能夠根據方法的請求參數對其結果進行緩存

@Cacheable 主要的參數
value 緩存的名稱,緩存中具體哪個數據庫,在 spring 配置文件中定義,必須指定至少一個 例如:
@Cacheable(value=”mycache”) 或者 
@Cacheable(value={”cache1”,”cache2”}
key 緩存的 key,可以為空,如果指定要按照 SpEL 表達式編寫,如果不指定,則缺省按照方法的所有參數進行組合,或者方法參數列表中的任意一個參數,或者字符串+參數組合

例如:
@Cacheable(value=”testcache”,key=”#userName”)

@Cacheable(value=”testcache”,key=” '字符串'+#userName”)

condition 緩存的條件,可以為空,使用 SpEL 編寫,返回 true 或者 false,只有為 true 才進行緩存 例如:
@Cacheable(value=”testcache”,condition=”#userName.length()>2”)
 
表 2. @CachePut 作用和配置方法
@CachePut 的作用 主要針對方法配置,能夠根據方法的請求參數對其結果進行緩存,和 @Cacheable 不同的是,它每次都會觸發真實方法的調用
@CachePut 主要的參數
value 緩存的名稱,在 spring 配置文件中定義,必須指定至少一個 例如:
@Cacheable(value=”mycache”) 或者 
@Cacheable(value={”cache1”,”cache2”}
key 緩存的 key,可以為空,如果指定要按照 SpEL 表達式編寫,如果不指定,則缺省按照方法的所有參數進行組合 例如:
@Cacheable(value=”testcache”,key=”#userName”)
condition 緩存的條件,可以為空,使用 SpEL 編寫,返回 true 或者 false,只有為 true 才進行緩存 例如:
@Cacheable(value=”testcache”,condition=”#userName.length()>2”)
 
表 3. @CacheEvict 作用和配置方法
@CachEvict 的作用 主要針對方法配置,能夠根據一定的條件對緩存進行清空
@CacheEvict 主要的參數
value 緩存的名稱,在 spring 配置文件中定義,必須指定至少一個 例如:
@CachEvict(value=”mycache”) 或者 
@CachEvict(value={”cache1”,”cache2”}
key 緩存的 key,可以為空,如果指定要按照 SpEL 表達式編寫,如果不指定,則缺省按照方法的所有參數進行組合 例如:
@CachEvict(value=”testcache”,key=”#userName”)
condition 緩存的條件,可以為空,使用 SpEL 編寫,返回 true 或者 false,只有為 true 才清空緩存 例如:
@CachEvict(value=”testcache”,
condition=”#userName.length()>2”)
allEntries 是否清空所有緩存內容,缺省為 false,如果指定為 true,則方法調用后將立即清空所有緩存 例如:
@CachEvict(value=”testcache”,allEntries=true)
beforeInvocation 是否在方法執行前就清空,缺省為 false,如果指定為 true,則在方法還沒有執行的時候就清空緩存,缺省情況下,如果方法執行拋出異常,則不會清空緩存 例如:
@CachEvict(value=”testcache”,beforeInvocation=true)

 

*************************************************************************************************************************************************************************************

*************************************************************************************************************************************************************************************

spEL表達式的使用方法:http://docs.spring.io/spring/docs/4.2.x/spring-framework-reference/html/expressions.html

關於注解實現Redis緩存的方法,只有將key設計的合理且強大,整個的緩存在項目中才能通用且高效。否則,就像我上面的簡單的例子一樣,真的是搞笑了。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM