這篇文章主要為大家展示了“如何集成Spring redis緩存”,內(nèi)容簡而易懂,條理清晰,希望能夠幫助大家解決疑惑,下面讓小編帶領(lǐng)大家一起研究并學(xué)習(xí)一下“如何集成Spring Redis緩存”這篇文章吧。
網(wǎng)站建設(shè)哪家好,找創(chuàng)新互聯(lián)!專注于網(wǎng)頁設(shè)計、網(wǎng)站建設(shè)、微信開發(fā)、小程序定制開發(fā)、集團(tuán)企業(yè)網(wǎng)站建設(shè)等服務(wù)項(xiàng)目。為回饋新老客戶創(chuàng)新互聯(lián)還提供了軹城免費(fèi)建站歡迎大家使用!
一、添加依賴
<!--緩存--> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-context-support</artifactId> <version>4.3.14.RELEASE</version> </dependency> <!--redis--> <dependency> <groupId>org.springframework.data</groupId> <artifactId>spring-data-redis</artifactId> <version>1.8.10.RELEASE</version> </dependency> <dependency> <groupId>org.apache.commons</groupId> <artifactId>commons-pool2</artifactId> <version>2.4.3</version> </dependency> <dependency> <groupId>redis.clients</groupId> <artifactId>jedis</artifactId> <version>2.9.0</version> </dependency>
二、配置
增加spring-redis.xml
配置文件,內(nèi)容如下:
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:cache="http://www.springframework.org/schema/cache" xmlns:util="http://www.springframework.org/schema/util" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd http://www.springframework.org/schema/cache http://www.springframework.org/schema/cache/spring-cache.xsd http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util.xsd"> <bean id="jedisPoolConfig" class="redis.clients.jedis.JedisPoolConfig"> <property name="maxIdle" value="${redis.pool.maxIdle}"/> <property name="maxTotal" value="${redis.pool.maxTotal}"/> <property name="maxWaitMillis" value="${redis.pool.maxWaitMillis}"/> <property name="testOnBorrow" value="${redis.pool.testOnBorrow}"/> <property name="testOnReturn" value="${redis.pool.testOnReturn}"/> </bean> <bean id="jedisConnectionFactory" class="org.springframework.data.redis.connection.jedis.JedisConnectionFactory"> <property name="hostName" value="${redis.master.ip}"/> <property name="port" value="${redis.master.port}"/> <property name="poolConfig" ref="jedisPoolConfig"/> </bean> <bean id="redisKeySerializer" class="org.springframework.data.redis.serializer.StringRedisSerializer"/> <bean id="redisValueSerializer" class="org.springframework.data.redis.serializer.JdkSerializationRedisSerializer"/> <bean id="redisTemplate" class="org.springframework.data.redis.core.RedisTemplate"> <property name="connectionFactory" ref="jedisConnectionFactory"/> <property name="keySerializer" ref="redisKeySerializer"/> <property name="hashKeySerializer" ref="redisKeySerializer"/> <property name="valueSerializer" ref="redisValueSerializer"/> <property name="hashValueSerializer" ref="redisValueSerializer"/> </bean> <!--在 redis.properties 配置緩存詳細(xì)信息--> <util:properties id="redisExpires" location="classpath*:META-INF/spring/redis.properties"/> <bean id="cacheManager" class="org.springframework.data.redis.cache.RedisCacheManager"> <constructor-arg index="0" ref="redisTemplate"/> <!--默認(rèn)緩存 10 分鐘--> <property name="defaultExpiration" value="600"/> <property name="usePrefix" value="true"/> <property name="expires" ref="redisExpires"/> </bean> <!--啟用 cache 注解--> <cache:annotation-driven cache-manager="cacheManager" proxy-target-class="true"/> </beans>
在 src/main/resources/ 下面如果沒有META-INF/spring/
目錄就創(chuàng)建一個,然后增加 redis.properties 配置,示例如下:
# 緩存名=有效時間 halfHour=1800 oneHour=3600 oneDay=86400 webSession=1800 user=1800
除了上面配置外,在系統(tǒng)的 application.properties 中還需要提供下面幾個配置:
# redis 連接配置 redis.master.ip=10.10.10.100 redis.master.port=6379 # redis 連接池配置 redis.pool.maxIdle=200 redis.pool.maxTotal=1024 redis.pool.maxWaitMillis=1000 redis.pool.testOnBorrow=true redis.pool.testOnReturn=true
三、通過注解方式使用緩存
示例中,redis.propreties 配置如下:
# 數(shù)據(jù)庫定義,緩存 30 天 databaseDef=2592000 # 數(shù)據(jù)庫元數(shù)據(jù),緩存 1 小時 databaseMeta=3600
這個示例在數(shù)據(jù)庫服務(wù)上配置的,數(shù)據(jù)庫服務(wù)中,查詢次數(shù)遠(yuǎn)遠(yuǎn)大于新增、修改、刪除的次數(shù),非常適合使用緩存。
1. 緩存數(shù)據(jù) @Cacheable
@Override @Cacheable(value = "databaseDef", key = "'all'") public List<DatabaseDefinitionVo> selectAll() { return databaseDefinitionDao.selectAllVo(); }
特別注意:所有這些注解中,key 的值是 Spel 表達(dá)式,必須按照 Spel 要求來寫。上面這個例子中,直接定義返回值的 key 是 all 字符串,需要加上單引號' 括起來,下面還有其他用法。
在例子中,下面的方法也使用了這個注解:
@Override @Cacheable(value = "databaseDef", key = "#id.toString()") public DatabaseDefinition selectByPrimaryKey(Long id) { Assert.notNull(id, "數(shù)據(jù)庫 ID 不能為空!"); DatabaseDefinition definition = databaseDefinitionDao.selectByPrimaryKey(id); Assert.notNull(definition, "數(shù)據(jù)庫定義不存在!"); return definition; }
在上面注解中,key
中的 #id
指的是參數(shù)中的 id,在 IDEA 中會有自動提示。.toString()
是調(diào)用 id
的方法,在系統(tǒng)中規(guī)定了 key 必須是字符串類型,所以當(dāng)類型是 Long 的時候,需要轉(zhuǎn)換。
使用緩存的目的就是為了減少上面兩個方法調(diào)用時減少和數(shù)據(jù)庫的交互,減小數(shù)據(jù)庫的壓力,這是兩個主要的緩存數(shù)據(jù)的方法,下面的幾個操作都和上面這兩個方法有一定的關(guān)系。
重點(diǎn):這里以及下面幾個注解中,都指定了
value = "databaseDef"
,這里的意思是說,要使用前面配置中的 databaseDef 對應(yīng)的配置,也就是會緩存 30天。
2. 更新緩存 @CachePut
@Override @CachePut(value = "databaseDef", key = "#result.id.toString()") public DatabaseDefinition save(DatabaseDefinition definition, CurrentUser userModel) throws ServiceException { //代碼 return definition; }
更新緩存的方法需要注意的是返回值,在上面 save 方法中,有可能是新增,有可能是更新,不管是那個操作,當(dāng)操作完成后,上面注解會根據(jù) key 的值生成 key,然后將方法的返回值作為 value 保存到緩存中。
這里 key 的寫法中 #result 指代返回值,.id 是返回值的屬性,.toString() 是調(diào)用 id 屬性的方法,在系統(tǒng)中規(guī)定了 key 必須是字符串類型,所以當(dāng)類型是 Long 的時候,需要轉(zhuǎn)換。
這個方法上加的緩存還有問題,當(dāng)新增或者更新后,通過 selectAll() 返回的值已經(jīng)發(fā)生了變化,但是這里沒有清除 all 的緩存值,會導(dǎo)致 selectAll() 出現(xiàn)臟數(shù)據(jù),下面會通過 @Caching 注解改造這里。
3. 清除緩存 @CacheEvict
@Override @CacheEvict(value = "databaseDef", key = "#id.toString()") public void deleteByPrimaryKey(Long id) throws ServiceException { DatabaseDefinition definition = selectByPrimaryKey(id); if (definition.getLoadState().equals(DatabaseDefinition.LoadState.UP)) { throw new ServiceException("請先卸載數(shù)據(jù)庫!"); } databaseDefinitionDao.deleteByPrimaryKey(id); }
在上面新增或者修改的時候根據(jù) id 緩存或者更新了緩存數(shù)據(jù),這里當(dāng)刪除數(shù)據(jù)的時候,還需要清空對應(yīng)的緩存數(shù)據(jù)。
在上面注解中,key 中的 #id 指的是參數(shù)中的 id,在 IDEA 中會有自動提示。
這個方法上加的緩存還有問題,當(dāng)刪除后,通過 selectAll() 返回的值已經(jīng)發(fā)生了變化,但是這里沒有清除 all 的緩存值,會導(dǎo)致 selectAll() 出現(xiàn)臟數(shù)據(jù),下面會通過 @Caching 注解改造這里。
4. 組合使用 @Caching
上面兩個注解中,都提到了臟數(shù)據(jù),通過 @Caching 注解可以解決這個問題。
先修改第二個注解,來解決 save 時的臟數(shù)據(jù):
@Override @Caching(put = @CachePut(value = "databaseDef", key = "#result.id.toString()"), evict = @CacheEvict(value = "databaseDef", key = "'all'")) public DatabaseDefinition save(DatabaseDefinition definition, CurrentUser userModel) throws ServiceException { //其他代碼 return definition; }
前面說明,新增或者修改的時候,all 緩存中的數(shù)據(jù)已經(jīng)不對了,因此這里在 put 的同時,使用 evict 將 'all' 中的數(shù)據(jù)清除,這就保證了 selelctAll 下次調(diào)用時,會重新從庫中讀取數(shù)據(jù)。
對上面的刪除方法,也進(jìn)行類似的修改:
@Override @Caching(evict = { @CacheEvict(value = "databaseDef", key = "#id.toString()"), @CacheEvict(value = "databaseDef", key = "'all'") }) public void deleteByPrimaryKey(Long id) throws ServiceException { DatabaseDefinition definition = selectByPrimaryKey(id); if (definition.getLoadState().equals(DatabaseDefinition.LoadState.UP)) { throw new ServiceException("請先卸載數(shù)據(jù)庫!"); } databaseDefinitionDao.deleteByPrimaryKey(id); }
注意這里的 evict 是個數(shù)組,里面配置了兩個清除緩存的配置。
5. 全局配置 @CacheConfig
在上面所有例子中,都指定了 value = "databaseDef",實(shí)際上可以通過在類上使用 @CacheConfig 注解配置當(dāng)前類中的 cacheNames 值,配置后,如果和類上的 value 一樣就不需要在每個注解單獨(dú)配置。只有不同時再去指定,方法上的 value 值優(yōu)先級更高。
@Service @CacheConfig(cacheNames = "databaseDef") public class DatabaseDefinitionServiceImpl implements DatabaseDefinitionService, DatabaseSqlExecuteService, ApplicationListener {
有了上面配置后,其他緩存名字相同的地方可以簡化,例如刪除方法修改后如下:
@Override @Caching(evict = { @CacheEvict(key = "#id.toString()"), @CacheEvict(key = "'all'") }) public void deleteByPrimaryKey(Long id) throws ServiceException { DatabaseDefinition definition = selectByPrimaryKey(id); if (definition.getLoadState().equals(DatabaseDefinition.LoadState.UP)) { throw new ServiceException("請先卸載數(shù)據(jù)庫!"); } databaseDefinitionDao.deleteByPrimaryKey(id); }
其他例子
除了上面針對 databaseDef 的緩存外,還有 databaseMeta 的配置:
@Override @Cacheable(value = "databaseMeta", key = "#databaseId.toString()") public List<TableVo> selectTablesByDatabaseId(Long databaseId) throws Exception { //代碼 } @Override @Cacheable(value = "databaseMeta", key = "#databaseId + '_' + #tableName") public TableVo selectTableByDatabaseIdAndTableName(Long databaseId, String tableName) throws Exception { //代碼 }
這兩個方法是獲取數(shù)據(jù)庫元數(shù)據(jù)的,只有修改數(shù)據(jù)庫表的時候才會變化,因此不存在清除緩存的情況,但是萬一修改表后,想要新的元數(shù)據(jù),該怎么辦?
因此增加了一個空的方法來清空數(shù)據(jù),方法如下:
@Override @CacheEvict(value = "databaseMeta", allEntries = true) public void cleanTablesCache() { }
這里指定了 databaseMeta,通過 allEntries = true 清空所有 key 的緩存。通過這個方法可以保證在有需要的時候清空所有元數(shù)據(jù)的緩存。
實(shí)際上如果想要更精確的清除,可以傳入要清除的 databaseId 和 tableName 來更精確的清除。
增加緩存后的效果
調(diào)用 selectTablesByDatabaseId 多次時,輸出的日志如下:
INFO c.n.d.u.DynamicDataSource - 當(dāng)前數(shù)據(jù)源:默認(rèn)數(shù)據(jù)源
DEBUG c.n.d.DataScopeContextProviderFilter - 服務(wù)調(diào)用返回前清除數(shù)據(jù)權(quán)限信息
INFO c.n.d.u.DynamicDataSource - 當(dāng)前數(shù)據(jù)源:默認(rèn)數(shù)據(jù)源
DEBUG c.n.d.d.D.selectByPrimaryKey - ==> Preparing: SELECT xxx (隱藏完整 SQL)
DEBUG c.n.d.d.D.selectByPrimaryKey - ==> Parameters: 1(Long)
DEBUG c.n.d.d.D.selectByPrimaryKey - <== Total: 1
INFO c.n.d.u.DynamicDataSource - 當(dāng)前數(shù)據(jù)源:10.10.10.130/datareporting
DEBUG c.n.d.DataScopeContextProviderFilter - 服務(wù)調(diào)用返回前清除數(shù)據(jù)權(quán)限信息
INFO c.n.d.u.DynamicDataSource - 當(dāng)前數(shù)據(jù)源:默認(rèn)數(shù)據(jù)源
DEBUG c.n.d.DataScopeContextProviderFilter - 服務(wù)調(diào)用返回前清除數(shù)據(jù)權(quán)限信息
INFO c.n.d.u.DynamicDataSource - 當(dāng)前數(shù)據(jù)源:默認(rèn)數(shù)據(jù)源
DEBUG c.n.d.DataScopeContextProviderFilter - 服務(wù)調(diào)用返回前清除數(shù)據(jù)權(quán)限信息
從日志可以看出來,只有第一次進(jìn)行了數(shù)據(jù)庫查詢,后續(xù)通過日志看不到數(shù)據(jù)庫操作。
調(diào)用清空緩存后,會再次查詢數(shù)據(jù)庫。
初次調(diào)用時,WEB請求花了 700多ms,后面再次調(diào)用時,平均不到 30 ms,這就是緩存最明顯的作用。
連接到 redis 服務(wù)后,查看所有 key,結(jié)果如下:
redis@redissvr:~$ redis-cli
127.0.0.1:6379> keys *
1) "databaseMeta:1"
2) "databaseDef:all"
127.0.0.1:6379>
緩存中的數(shù)據(jù)都有 value 前綴,上面緩存了 all 和 id 為 1 的數(shù)據(jù)。
緩存注解是一種最簡單的緩存方式,但是需要配合 value 屬性的配置來使用,許多時候我們可能需要更精確的控制緩存,此時可以使用 RedisTemplate 來控制。
四、通過 RedisTemplate 使用緩存
有關(guān)這部分的詳細(xì)用法可以從網(wǎng)上搜索相關(guān)內(nèi)容進(jìn)行學(xué)習(xí),這里列舉一個簡單的例子。
針對前面的 selectAll 我們換一種方式進(jìn)行緩存。
首先注入下面的接口:
@Resource(name = "redisTemplate") private ValueOperations<String, List> valueOper;
修改 selectAll 方法如下:
@Override //@Cacheable(key = "'all'") public List<DatabaseDefinitionVo> selectAll() { List<DatabaseDefinitionVo> vos = valueOper.get("databaseDef:all"); if(vos != null){ return vos; } vos = databaseDefinitionDao.selectAllVo(); //緩存 1 小時 valueOper.set("databaseDef:all", vos, 1, TimeUnit.HOURS); return vos; }
首先通過valueOper.get("databaseDef:all")
嘗試獲取緩存信息,如果存在就直接返回。
如果不存在,就查詢數(shù)據(jù)庫,然后將查詢結(jié)果通過 set 進(jìn)行緩存。
特別注意: 上面的 key,寫的是 "databaseDef:all",也就是前綴需要自己加上,如果直接寫成 all,在 Redis 中的 key 就是 all,不會自動增加前綴。
如果沒有前綴,那么當(dāng)不同系統(tǒng)都使用 all 時,數(shù)據(jù)就會混亂!
五、Redis 服務(wù)器配置注意事項(xiàng)
內(nèi)網(wǎng)使用的服務(wù)器,特殊配置如下:
# By default protected mode is enabled. You should disable it only if # you are sure you want clients from other hosts to connect to Redis # even if no authentication is configured, nor a specific set of interfaces # are explicitly listed using the "bind" directive. # protected-mode yes protected-mode no
關(guān)閉了保護(hù)模式。
# IF YOU ARE SURE YOU WANT YOUR INSTANCE TO LISTEN TO ALL THE INTERFACES # JUST COMMENT THE FOLLOWING LINE. # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ # bind 127.0.0.1
注釋了綁定的 IP,這樣可以讓所有電腦訪問 Redis。
以上是“如何集成Spring Redis緩存”這篇文章的所有內(nèi)容,感謝各位的閱讀!相信大家都有了一定的了解,希望分享的內(nèi)容對大家有所幫助,如果還想學(xué)習(xí)更多知識,歡迎關(guān)注創(chuàng)新互聯(lián)行業(yè)資訊頻道!
網(wǎng)頁標(biāo)題:如何集成SpringRedis緩存
網(wǎng)頁URL:http://aaarwkj.com/article28/ijhgjp.html
成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供網(wǎng)站改版、網(wǎng)站排名、營銷型網(wǎng)站建設(shè)、網(wǎng)站策劃、響應(yīng)式網(wǎng)站、網(wǎng)頁設(shè)計公司
聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請盡快告知,我們將會在第一時間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場,如需處理請聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時需注明來源: 創(chuàng)新互聯(lián)