首先不得不服Spring这个宇宙无敌的开源框架,几乎整合了所有流行的其它框架,http://projects.spring.io/spring-data/ 从这上面看,当下流行的redis、solr、hadoop、mongoDB、couchBase... 全都收入囊中。对于redis整合而言,主要用到的是spring-data-redis
使用步骤:
一、pom添加依赖项
<dependency> <groupId>org.springframework.data</groupId> <artifactId>spring-data-redis</artifactId> <version>1.4.1.RELEASE</version> </dependency>
其它Spring必备组件,比如Core,Beans之类,大家自行添加吧
观察一下:
jedis、jredis等常用java的redis client已经支持了,不知道以后会不会集成Redisson,spring-data-redis提供了一个非常有用的类:StringRedisTemplate
对于大多数缓存应用场景而言,字符串是最常用的缓存项,用StringRedisTemplate可以轻松应付。
二、spring配置
1 <bean id="redisSentinelConfiguration" 2 class="org.springframework.data.redis.connection.RedisSentinelConfiguration"> 3 <property name="master"> 4 <bean class="org.springframework.data.redis.connection.RedisNode"> 5 <property name="name" value="mymaster"></property> 6 </bean> 7 </property> 8 <property name="sentinels"> 9 <set> 10 <bean class="org.springframework.data.redis.connection.RedisNode"> 11 <constructor-arg index="0" value="10.6.1**.**5" /> 12 <constructor-arg index="1" value="7031" /> 13 </bean> 14 <bean class="org.springframework.data.redis.connection.RedisNode"> 15 <constructor-arg index="0" value="10.6.1**.**6" /> 16 <constructor-arg index="1" value="7031" /> 17 </bean> 18 <bean class="org.springframework.data.redis.connection.RedisNode"> 19 <constructor-arg index="0" value="10.6.1**.**1" /> 20 <constructor-arg index="1" value="7031" /> 21 </bean> 22 </set> 23 </property> 24 </bean> 25 26 <bean id="jedisConnFactory" 27 class="org.springframework.data.redis.connection.jedis.JedisConnectionFactory"> 28 <constructor-arg ref="redisSentinelConfiguration" /> 29 </bean> 30 31 <bean id="stringRedisTemplate" class="org.springframework.data.redis.core.StringRedisTemplate"> 32 <property name="connectionFactory" ref="jedisConnFactory" /> 33 </bean>
这里我们使用Sentinel模式来配置redis连接,从上篇学习知道,sentinel是一种高可用架构,个人推荐在生产环境中使用sentinel模式。
三、单元测试
1 @Test 2 public void testSpringRedis() { 3 ConfigurableApplicationContext ctx = null; 4 try { 5 ctx = new ClassPathXmlApplicationContext("spring.xml"); 6 7 StringRedisTemplate stringRedisTemplate = ctx.getBean("stringRedisTemplate", StringRedisTemplate.class); 8 9 // String读写 10 stringRedisTemplate.delete("myStr"); 11 stringRedisTemplate.opsForValue().set("myStr", "http://yjmyzz.cnblogs.com/"); 12 System.out.println(stringRedisTemplate.opsForValue().get("myStr")); 13 System.out.println("---------------"); 14 15 // List读写 16 stringRedisTemplate.delete("myList"); 17 stringRedisTemplate.opsForList().rightPush("myList", "A"); 18 stringRedisTemplate.opsForList().rightPush("myList", "B"); 19 stringRedisTemplate.opsForList().leftPush("myList", "0"); 20 List<String> listCache = stringRedisTemplate.opsForList().range( 21 "myList", 0, -1); 22 for (String s : listCache) { 23 System.out.println(s); 24 } 25 System.out.println("---------------"); 26 27 // Set读写 28 stringRedisTemplate.delete("mySet"); 29 stringRedisTemplate.opsForSet().add("mySet", "A"); 30 stringRedisTemplate.opsForSet().add("mySet", "B"); 31 stringRedisTemplate.opsForSet().add("mySet", "C"); 32 Set<String> setCache = stringRedisTemplate.opsForSet().members( 33 "mySet"); 34 for (String s : setCache) { 35 System.out.println(s); 36 } 37 System.out.println("---------------"); 38 39 // Hash读写 40 stringRedisTemplate.delete("myHash"); 41 stringRedisTemplate.opsForHash().put("myHash", "PEK", "北京"); 42 stringRedisTemplate.opsForHash().put("myHash", "SHA", "上海虹桥"); 43 stringRedisTemplate.opsForHash().put("myHash", "PVG", "浦东"); 44 Map<Object, Object> hashCache = stringRedisTemplate.opsForHash() 45 .entries("myHash"); 46 for (Map.Entry<Object, Object> entry : hashCache.entrySet()) { 47 System.out.println(entry.getKey() + " - " + entry.getValue()); 48 } 49 50 System.out.println("---------------"); 51 52 } finally { 53 if (ctx != null && ctx.isActive()) { 54 ctx.close(); 55 } 56 } 57 58 }
运行一下,行云流水般的输出:
...
信息: Created JedisPool to master at 10.6.144.***:7030
http://yjmyzz.cnblogs.com/
---------------
0
A
B
---------------
C
B
A
---------------
SHA - 上海虹桥
PVG - 浦东
PEK - 北京
---------------
...
注意红色标出部分,从eclipse控制台的输出,还能看出当前的master是哪台服务器
三、POJO对象的缓存
Spring提供的StringRedisTemplate只能对String操作,大多数情况下已经够用,但如果真需要向redis中存放POJO对象也不难,我们可以参考StringRedisTemplate的源码,扩展出ObjectRedisTemplate
然后就可以这样用了:
其中SampleBean的定义如下:
注:由于不是标准的String类型,所以在redis控制台,用./redis-cli get myBean是看不到缓存内容的,只能得到nil的输出,不要误以为set没成功!通过代码是可以正常get到缓存值的。
另外关于POJO对象的缓存,还有二个注意事项:
a) POJO类必须要有默认的无参构造函数,否则反序列化时会报错
b) ObjectRedisTemplate<T>中的T不能是接口,比如 DomainModelA继承自接口 IModelA,使用ObjectRedisTemplate时,要写成ObjectRedisTemplate<DomainModelA>而不是ObjectRedisTemplate<IModelA>,否则反序列化时也会出错