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

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

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

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

 

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

   2.配置文件添加配置數據庫

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

   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.配置文件添加配置app

複製代碼
#============================#
#==== 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設計的合理且強大,整個的緩存在項目中才能通用且高效。不然,就像我上面的簡單的例子同樣,真的是搞笑了。

相關文章
相關標籤/搜索