javascript
使用Spring Data Redis进行缓存
在下面的示例中,我將向您展示如何使用Spring Data – Redis項目作為Spring 3.1中引入的Spring Cache Abstraction的緩存提供程序。 我對如何使用Spring的基于Java的配置有很多疑問,因此我將同時提供基于XML和Java的配置供您查看。
依存關系
在此示例中使用了以下依賴關系:
代碼和配置
下面的HelloService示例非常簡單。 正如您將在實現中看到的那樣,它只返回一個字符串,該字符串的前綴是“ Hello”,該字符串在傳入的名稱之前。
package com.joshuawhite.example.service;public interface HelloService {String getMessage(String name);}查看一下HelloServiceImpl類(如下),您可以看到我正在利用Spring的@Cacheable批注為getMessage方法添加緩存功能。 有關此批注功能的更多詳細信息,請參閱Cache Abstraction文檔 。 為了娛樂,我使用Spring Expression Language(SpEL)定義條件。 在此示例中,僅當傳入的名稱為“ Joshua”時才緩存方法響應。
package com.joshuawhite.example.service;import org.springframework.cache.annotation.Cacheable; import org.springframework.stereotype.Service;@Service('helloService') public class HelloServiceImpl implements HelloService {/*** Using SpEL for conditional caching - only cache method executions when* the name is equal to 'Joshua'*/@Cacheable(value='messageCache', condition=''Joshua'.equals(#name)')public String getMessage(String name) {System.out.println('Executing HelloServiceImpl' +'.getHelloMessage(\'' + name + '\')');return 'Hello ' + name + '!';}}下面的App類包含我們的main方法,用于在基于XML和Java的配置之間進行選擇。 每個System.out.println都用于演示何時進行緩存。 提醒一下,我們只希望傳入“ Joshua”的方法執行將被緩存。 當我們稍后查看程序輸出時,這將更加清楚。
package com.joshuawhite.example;import org.springframework.cache.Cache; import org.springframework.cache.CacheManager; import org.springframework.context.ApplicationContext; import org.springframework.context.annotation.AnnotationConfigApplicationContext; import org.springframework.context.support.GenericXmlApplicationContext;import com.joshuawhite.example.config.AppConfig; import com.joshuawhite.example.service.HelloService;public class App {public static void main(String[] args) {boolean useJavaConfig = true;ApplicationContext ctx = null;//Showing examples of both Xml and Java based configurationif (useJavaConfig ) {ctx = new AnnotationConfigApplicationContext(AppConfig.class);}else {ctx = new GenericXmlApplicationContext('/META-INF/spring/app-context.xml');}HelloService helloService = ctx.getBean('helloService', HelloService.class);//First method execution using key='Josh', not cachedSystem.out.println('message: ' + helloService.getMessage('Josh'));//Second method execution using key='Josh', still not cachedSystem.out.println('message: ' + helloService.getMessage('Josh'));//First method execution using key='Joshua', not cachedSystem.out.println('message: ' + helloService.getMessage('Joshua'));//Second method execution using key='Joshua', cachedSystem.out.println('message: ' + helloService.getMessage('Joshua'));System.out.println('Done.');}}請注意,在使用基于XML的配置時,仍使用組件掃描。 您可以看到我在上面的HelloServiceImpl.java第6行上使用@Service批注。 接下來,我們將看看如何配置jedisConnectionFactory , redisTemplate和cacheManager 。
配置JedisConnectionFactory
在此示例中,我選擇使用Jedis作為我們的Java客戶端,因為它在Redis站點上被列為Java的“推薦”客戶端庫。 如您所見,設置非常簡單。 當我顯式設置use-pool = true時,它的源代碼指示這是默認設置。 如果未顯式設置,則JedisConnectionFactory還提供以下默認值:
- hostName =” localhost”
- 端口= 6379
- 超時= 2000毫秒
- 數據庫= 0
- usePool = true
注意:盡管數據庫索引是可配置的,但是JedisConnectionFactory僅支持一次連接到一個Redis數據庫。 由于Redis是單線程的,因此建議您設置Redis的多個實例,而不是在單個進程中使用多個數據庫。 這使您可以獲得更好的CPU /資源利用率。 如果計劃使用redis-cluster,則僅支持單個數據庫。 有關連接池中使用的默認值的更多信息,請查看JedisPoolConfig或Apache Commons Pool org.apache.commons.pool.impl.GenericObjectPool.Config以及其中的實現。 org.apache.commons.pool.impl.GenericObjectPool類。
配置RedisTemplate
正如您從Spring“模板”類中所期望的那樣, RedisTemplate負責序列化和連接管理,并且( RedisTemplate您正在使用連接池)是線程安全的。 默認情況下,RedisTemplate使用Java序列化( JdkSerializationRedisSerializer )。 請注意,將數據序列化為Redis實質上使Redis成為“不透明”緩存。 雖然其他序列化程序允許您將數據映射到Redis,但我發現序列化(尤其是在處理對象圖時)使用起來更快,更簡單。 就是說,如果您要求其他非Java應用程序能夠訪問此數據,則映射是您最好的即用型選擇。 我在使用Hessian和Google Protocol Buffers / proststuff方面有豐富的經驗。 我將在以后的文章中分享RedisSerializer一些示例實現。
配置RedisCacheManager
配置RedisCacheManager很簡單。 提醒一下, RedisCacheManager依賴于RedisTemplate ,后者依賴于連接工廠(在我們的情況下為JedisConnectionFactory ,該連接工廠一次只能連接到一個數據庫。 解決方法是,RedisCacheManager可以為您的緩存鍵設置前綴。
警告:在處理其他緩存解決方案時,Spring的CacheManger通常包含一個由單獨的緩存支持的Cache映射(每個實現類似功能的映射)的實現。 使用默認的RedisCacheManager配置,情況并非如此。 根據RedisCacheManager上的javadoc注釋,不清楚這是錯誤還是僅是不完整的文檔。
“ ...默認情況下,通過添加前綴(用作名稱空間)來保存密鑰。”
雖然RedisCacheManager配置的DefaultRedisCachePrefix當然支持此功能,但默認情況下未啟用它。 結果,當您向RedisCacheManager詢問給定名稱的Cache時,它只是創建一個指向相同數據庫的新Cache實例。 結果, Cache實例完全相同。 相同的鍵將在所有Cache實例中檢索相同的值。
正如javadoc注釋所暗示的那樣,前綴可用于設置客戶端管理的名稱空間(Redis本身不支持此功能),這些名稱空間實際上在同一數據庫內創建“虛擬”緩存。 您可以通過使用Spring XML或Java配置調用redisCacheManager.setUsePrefix(true)來redisCacheManager.setUsePrefix(true)此功能。
<?xml version='1.0' encoding='UTF-8'?> <beansxmlns='http://www.springframework.org/schema/beans'xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance'xmlns:context='http://www.springframework.org/schema/context'xmlns:c='http://www.springframework.org/schema/c'xmlns:p='http://www.springframework.org/schema/p'xmlns:cache='http://www.springframework.org/schema/cache'xsi:schemaLocation='http://www.springframework.org/schema/beansvhttp://www.springframework.org/schema/beans/spring-beans.xsdhttp://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsdhttp://www.springframework.org/schema/cache http://www.springframework.org/schema/cache/spring-cache.xsd'><context:component-scan base-package='com.joshuawhite.example.service' /><context:property-placeholder location='classpath:/redis.properties'/><!-- turn on declarative caching --><cache:annotation-driven /><!-- Jedis ConnectionFactory --><beanid='jedisConnectionFactory'class='org.springframework.data.redis.connection.jedis.JedisConnectionFactory'p:host-name='${redis.host-name}'p:port='${redis.port}'p:use-pool='true'/><!-- redis template definition --><beanid='redisTemplate'class='org.springframework.data.redis.core.RedisTemplate'p:connection-factory-ref='jedisConnectionFactory'/><!-- declare Redis Cache Manager --><beanid='cacheManager'class='org.springframework.data.redis.cache.RedisCacheManager'c:template-ref='redisTemplate'/></beans>下面的Java配置與上面的XML配置等效。 人們通常會習慣使用PropertySourcesPlaceholderConfigurer 。 要做到這一點,你需要使用兩個 @PropertySource注釋和定義PropertySourcesPlaceholderConfigurer豆。 PropertySourcesPlaceholderConfigurer是不夠的。
package com.joshuawhite.example.config;import org.springframework.beans.factory.annotation.Value; import org.springframework.cache.CacheManager; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.ComponentScan; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.PropertySource; import org.springframework.context.support.PropertySourcesPlaceholderConfigurer; import org.springframework.data.redis.cache.RedisCacheManager; import org.springframework.data.redis.connection.jedis.JedisConnectionFactory; import org.springframework.data.redis.core.RedisTemplate;@Configuration @ComponentScan('com.joshuawhite.example') @PropertySource('classpath:/redis.properties') public class AppConfig {private @Value('${redis.host-name}') String redisHostName;private @Value('${redis.port}') int redisPort;@Beanpublic static PropertySourcesPlaceholderConfigurer propertySourcesPlaceholderConfigurer() {return new PropertySourcesPlaceholderConfigurer();}@BeanJedisConnectionFactory jedisConnectionFactory() {JedisConnectionFactory factory = new JedisConnectionFactory();factory.setHostName(redisHostName);factory.setPort(redisPort);factory.setUsePool(true);return factory;}@BeanRedisTemplate<Object, Object> redisTemplate() {RedisTemplate<Object, Object> redisTemplate = new RedisTemplate<Object, Object>();redisTemplate.setConnectionFactory(jedisConnectionFactory());return redisTemplate;}@BeanCacheManager cacheManager() {return new RedisCacheManager(redisTemplate());}}這是兩種配置都使用的屬性文件。 將下面的值替換為您使用的主機和端口。
redis.host-name=yourHostNameHere redis.port=6379輸出量
最后,這是我們簡短的示例應用程序的輸出。 請注意,無論我們調用getHelloMessage('Josh')多少次,方法響應都不會被緩存。 這是因為我們定義了一個條件(請參見HelloServiceImpl.java ,第13行),其中僅當名稱等于“ Joshua”時才緩存方法響應。 當我們第一次調用getHelloMessage('Joshua')時,將執行該方法。 但是,第二次不是。
Executing HelloServiceImpl.getHelloMessage('Josh') message: Hello Josh! Executing HelloServiceImpl.getHelloMessage('Josh') message: Hello Josh! Executing HelloServiceImpl.getHelloMessage('Joshua') message: Hello Joshua! Executing HelloServiceImpl.getHelloMessage('Joshua') message: Hello Joshua! Done. 到此,我們簡要概述了使用Spring Data Redis進行緩存的過程。
參考: Joshua White博客博客中來自JCG合作伙伴 Joshua White的Spring Data Redis緩存 。
翻譯自: https://www.javacodegeeks.com/2013/02/caching-with-spring-data-redis.html
總結
以上是生活随笔為你收集整理的使用Spring Data Redis进行缓存的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 邯郸商品房备案查询入口(邯郸商品房备案查
- 下一篇: 如何查找ddos攻击源(ddos怎么快速