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