Spring使用Redis操作key-value数据
-
首先需要使用Redis连接工厂获取Redis连接。
-
接着使用Redis连接创建Redis模板。
-
最后Redis模板进行Redis操作。
-
根据Redis连接工厂创建Redis模板。
-
使用Redis模板进行Redis操作。
连接到Redis
Spring提供了4个Redis连接工厂类,我们根据需要使用。
- JedisConnectionFactory
- JredisConnectionFactory
- LettuceConnectionFactory
- SrpConnectionFactory
这4个类都继承了RedisConnectionFactory接口
下面我们以JedisConnectionFactory为例,其他的都是类似的。
将JedisConnectionFactory bean将给Spring管理。
@Bean
public RedisConnectionFactory redisCF() {
return new JedisConnectionFactory();
}
如果使用默认的构造器,那么Redis连接会建立在localhost的6379端口,并且没有密码。
如果Redis服务器部署在其主机上和其他端口上,那么我们可以进行配置。同样,如果需要客户端认证(密码),我们可以配置密码。
@Bean
public RedisConnectionFactory redisCF() {
JedisConnectionFactory cf = new JedisConnectionFactory();
cf.setHostName("redis-server");
cf.setPort(7379);
cf.setPassword("abc");
return cf;
}
使用Redis Template
现在,我们可以根据Redis连接工厂创建Redis Template。
Spring提供了2个Redis Template模板:
- RedisTemplate:可以存储各种类型的key和value
- StringRedisTemplate:扩展了RedisTemplate,key和value只能是String
RedisConnectionFactory cf = ...;
RedisTemplate<String, Product> redis = new RedisTemplate<String, Product>();
redis.setConnectionFactory(cf);
RedisConnectionFactory cf = ...;
StringRedisTemplate redis = new StringRedisTemplate(cf);
如果Redis模板经常使用,那么我们可以设置为Spring的bean。
@Bean
public RedisTemplate<String, Product> redisTemplate(RedisConnectionFactory cf) {
RedisTemplate<String, Product> redis = new RedisTemplate<String, Product>();
redis.setConnectionFactory(cf);
return redis;
}
@Bean
public RedisConnectionFactory redisConnectionFactory(RedisConnectionFactory cf) {
return new RedisConnectionFactory(cf);
}
RedisTemplate的大多数操作都是如下子API提供的
以opsFor开头的方法是直接操作Redis,以bound开头的方法是绑定到某个key的key-value。
下面将会使用一些常用的操作
操作简单值
- 存储键值对
redisTemplate.opsForValue().set(key, value)
//demo
redisTemplate.opsForValue().set(product.getSku, product);
- 获取值
获取sku为"123456"的value
Value v = redisTemplate.opsForValue().get(key)
//demo
Product product = redisTemplate.opsForValue().get("123456");
如果没有key为"123456"的键值对,那么会返回null。
操作List
- 放到list的尾部
redisTemplate.opsForList().rightPush(key, value)
//demo
redisTemplate.opsForList().rightPush("cart", product);
在list的尾部放入value。如果没有这个key,那么会创建一个。
- 放到list的头部
redisTemplate.opsForList().leftPush(key, value)
//demo
redisTemplate.opsForList().leftPush("cart", product);
- 从list的头部/尾部弹出元素(弹出后list就不存在了)
Value v = redisTemplate.opsForList().leftPop(key)
Value v = redisTemplate.opsForList().rightPop(key)
//demo
Product first = redisTemplate.opsForList().leftPop("cart");
Product last = redisTemplate.opsForList().rightPop("cart");
- 获取list的某个范围的值的list(不会删除原有的元素)
List<Value> list = redisTemplate.opsForList().range(key, startIndex, endIndex)
//从startIndex到endIndex,这两个索引都包含
//demo
List<Product> list = redisTemplate.opsForList()/range("cart", 2, 12);
//获取索引从2到12的11个元素
操作Set
对于Set,我们不能像list一样根据索引获取元素,Set是无序的。
- 放入一个元素
redisTemplate.opsForSet().add(key, value)
//demo
redisTemplate.opsForSet().add("cart", product);
- 对于多个Set,可以获取他们的差异、交集和并集
redisTemplate.opsForSet().different(key1, key2)
redisTemplate.opsForSet().union(key1, key2)
redisTemplate.opsForSet().isect(key1, key2)
//demo
redisTemplate.opsForSet().different("cart1", "cart2")
redisTemplate.opsForSet().union("cart1", "cart2")
redisTemplate.opsForSet().isect("cart1", "cart2")
- 还可以从Set从随机获取一个元素
Value v = redisTemplate.opsForSet().randomMember(key)
//demo
Product product = redisTemplate.opsForSet().randomMember("cart");
绑定一个key
如果某个key的value经常使用,那么我们可以用一个变量绑定某个key的value,然后对这个变量的操作就是对value的操作。
下面以List为例
BoundListOperations<String, Product> cart = redisTemplate.boundListOps("cart");
Product product = cart.rightPop();
cart.rightPush(product1);
cart.rightPush(product2);
cart.rightPush(product3);
设置key和value的序列化器
当把数据保存到Redis key-value存储的时候,序列化器会对key和value进行序列化。Spring Data Redis提供了一下的序列化器:
- GenericToStringSerializer:使用Spring转换服务进行序列化;
- JacksonJsonRedisSerializer:使用Jackson 1,将对象序列化为JSON;
- Jackson2JsonRedisSerializer:使用Jackson 2,将对象序列化为JSON;
- JdkSerializationRedisSerializer:使用Java序列化;
- OxmSerializer:使用Spring O/X映射的编排器和解排器(marshaler和unmarshaler)实 现序列化,用于XML序列化;
- StringRedisSerializer:序列化String类型的key和value。
这些序列化器都实现了RedisSerializer接口。
RedisTemplate使用JdkSerializationRedisSerializer;StringRedisTemplate默认使用StringRedisSerializer。
但是我们可以根据需要分别设置key和value的序列化器。例如:现在我们想设置key为String保存,value以JSON格式保存。我们可以使用RedisTemplate对象的setKeySerializer()和setValueSerializer()方法。
@Bean
public RedisTemplate<String, Product> redisTemplate(RedisConnectionFactory cf) {
RedisTemplate<String, Product> redis = new RedisTemplate<String, Product>();
redis.setConnectionFactory(cf);
redis.setKeySerializer(new StringRedisSerializer());
redis.setValueSerializer(new Jackson2JsonRedisSerializer<Product>(Product.class));
return redis;
}