Spring中使用Redis
1. 配置环境
<!-- https://mvnrepository.com/artifact/redis.clients/jedis --> <dependency> <groupId>redis.clients</groupId> <artifactId>jedis</artifactId> <version>2.9.0</version> </dependency> <!-- https://mvnrepository.com/artifact/org.springframework.data/spring-data-redis --> <dependency> <groupId>org.springframework.data</groupId> <artifactId>spring-data-redis</artifactId> <version>1.7.2.RELEASE</version> </dependency>
这里值得注意的是:jar包和spring版本兼容的问题,笔者使用的jar包版本是1.7.2,而Spring的版本是4.3.2。如果使用其他版本的话,可能存在不兼容的问题。
2. 测试连接
@Test //测试是否连接成功 public void testConn(){ Jedis jedis = new Jedis("localhost",6379); // jedis.auth("password");//如果由密码的话 int i = 0; try{ long start = System.currentTimeMillis();//开始时间 while (true){ long end = System.currentTimeMillis(); if (end - start >= 1000){ break; } i++; jedis.set("test"+i,i+""); } }catch (Exception ex){ ex.printStackTrace(); }finally { jedis.close(); } System.out.println("Jedis每秒操作:"+i+"次"); }
运行结果:
Jedis每秒操作:23564次
3. 使用Redis连接池
Java Redis的连接池提供了类:redis.clients.jedis.JedisPool 用来创建Redis的连接池对象。使用这个对象,需要使用类:redis.clients.jedis.JedisPoolConfig来对连接池进行配置,如代码所示:
@Test //配置连接池 public void testJedisPool(){ JedisPoolConfig poolConfig = new JedisPoolConfig(); //最大空闲数 poolConfig.setMaxIdle(50); //最大连接数 poolConfig.setMaxTotal(100); //最大等待毫秒数 poolConfig.setMaxWaitMillis(20000); //使用配置创建连接池 JedisPool jedisPool = new JedisPool(poolConfig,"localhost"); //从连接池获取单个连接对象 Jedis jedis = jedisPool.getResource(); //如果需要密码 // jedis.auth("password"); }
4. RedisTemplate
由于Redis只能提供基于字符串型的操作,而在Java中 使用的却以类对象为主,所以需要Redis存储的字符串和Java对象进行互相转换。好在Spring对这些进行了封装和支持,它提供了序列化的设计框架和一些序列化的类,使用后可以通过序列化把Java对象封装,使得Redis能把器存储起来,并且在读的时候,再把由序列化过的字符串转化位Java对象。这样在Java中使用Redis就更简单了,所以更多的时候可以使用SPring提供的RedisTemplate的机制来使用Redis
使用RedisTemplate需要下载Spring-data-redis.jar,开头已经将对应maven坐标导入。下面看如何配置。
<bean id="poolConfig" class="redis.clients.jedis.JedisPoolConfig"> <property name="maxIdle" value="50"/><!-- 最大空闲数 --> <property name="maxTotal" value="100"/><!-- 最大连接数 --> <property name="maxWaitMillis" value="20000"/><!-- 最大等待时间 --> </bean> <!-- 在使用RedisTemplate之前需要配置Spring所提供的连接工厂 以:JedisConnectionFactory为例--> <bean id="connectionFactory" class="org.springframework.data.redis.connection.jedis.JedisConnectionFactory"> <property name="hostName" value="localhost"/> <property name="port" value="6379"/> <property name="poolConfig" ref="poolConfig"/> </bean> <!--对POJO的序列化存储配置 --> <!-- 配置Spring RedisTemplate --> <!-- value的序列化器 JdkSerializationRedisSerializer序列化器是对Java对象进行序列化以存储进Redis所需要的--> <bean id="jdkSerializationRedisSerializer" class="org.springframework.data.redis.serializer.JdkSerializationRedisSerializer"/> <!-- key的序列化器 --> <bean id="stringRedisSerializer" class="org.springframework.data.redis.serializer.StringRedisSerializer"/> <!-- 配置Spring RedisTemplate --> <bean id="redisTemplate" class="org.springframework.data.redis.core.RedisTemplate"> <property name="connectionFactory" ref="connectionFactory"/> <property name="keySerializer" ref="stringRedisSerializer"/> <property name="valueSerializer" ref="jdkSerializationRedisSerializer"/> </bean>
5. 使用Redis保存Java类对象
- 创建Account类,实现序列化接口。
public class Account implements Serializable { private Integer id; private Integer uid; private Double money; ***get/set*** }
- 使用RedisTemplate实现保存
@Test public void testJedisTemplate(){ ApplicationContext ac = new ClassPathXmlApplicationContext("classpath:applicationContext.xml"); RedisTemplate template = ac.getBean("redisTemplate", RedisTemplate.class); Account account = new Account(); account.setId(8); account.setUid(50); account.setMoney(4000D); template.opsForValue().set("account_1",account); Account account1 = (Account) template.opsForValue().get("account_1"); System.out.println(account1); }
注意:以上的操作都是基于RedisTemplate、基于连接池的操作,换句话说,并不能保证每次使用RedisTemplate是操作同一个 对Redis的连接。比如:
template.opsForValue().set("account_1",account); Account account1 = (Account) template.opsForValue().get("account_1");
set和get方法看起来简单,但是它可能就来自于同一个Redis连接池不同Redis的连接,为了使得所有的操作都来自于同一个连接,可以使用SessionCallback或者RedisCallback这两个接口,更多的时候使用的是SessionCallback这个接口,通过这个接口就可以把多个命令放入到同一个Redis连接中去执行,如下:
@Test //使用SessionCallback接口。 //目的:使多个命令放入到同一个Redis连接中 public void testSessionCallback(){ ApplicationContext ac = new ClassPathXmlApplicationContext("classpath:applicationContext.xml"); RedisTemplate template = ac.getBean("redisTemplate", RedisTemplate.class); Account account = new Account(); account.setId(9); account.setUid(50); account.setMoney(4000D); SessionCallback callback = new SessionCallback() { @Override public Object execute(RedisOperations ops) throws DataAccessException { ops.boundValueOps("account_2").set(account); return (Account)ops.boundValueOps("account_2").get(); } }; Account saveAccount = (Account)template.execute(callback); System.out.println(saveAccount); } //这样使得set和get命令就能够保证在同一个连接池的同一个Redis连接池进行操作。