之前的一篇文章提到了redis提供了5种数据类型可供存取,本文将使用string字符串的类型来演示数据的存取操作。
Redis是noSql数据库,没有表的概念,要实现与数据库的数据在redis中实现存取,需要使用json格式的文本作为redis与java对象相互交换数据的存取格式。本文使用Gson来将类对象转换为JSON格式的文本进行存储,也可以使用阿里的fastJson。在读取数据时再将JSON文本转换为java对象。
Redis采取的是key-value的形式存取数据,所以存入数据时需要生成一个唯一的key,后续的查询更新删除等一系列操作全都要依靠这个唯一的key值来进行。保存在redis的数据是默认永久存在的,可以指定一个时限来确定数据的生命周期,超过时限的数据将被redis自动清除。
首先我们需要创建redis服务类,需要用到redisTemplate。spring封装了redisTemplate对象来进行对redis的各种操作,它支持所有的redis原声的api。
根据数据类型的不同,redisTemplate中定义了对5种数据结构的操作,根据情况选用。
在这里我们要区分一下redisTemplate和stringRedisTemplate之间的区别。
stringRedisTemplate是继承redisTemplate的,两者的数据不共通的,有各自的工作空间,只能管理自己的数据。
stringRedisTemplate默认采用的是String的序列化策略,保存的key和value都是采用此序列化保存的。
redisTemplate默认采用的是JDK的序列化策略,保存的key和value都是采用此序列化保存的。
在操作数据的时候,比如说存入数据会将数据先序列化成字节数组然后在存入Redis数据库,这个时候打开Redis查看的时候,你会看到你的数据不是以可读的形式展现的,而是以字节数组显示。当然从Redis获取数据的时候也会默认将数据当做字节数组转化,这样就会导致一个问题,当需要获取的数据不是以字节数组存在redis当中而是正常的可读的字符串的时候。
当Redis当中的数据值是以可读的形式显示出来的时候,只能使用StringRedisTemplate才能获取到里面的数据。所以当你使用RedisTemplate获取不到数据的时候请检查一下是不是Redis里面的数据是可读形式而非字节数组。
总结:当你的redis数据库里面本来存的是字符串数据或者你要存取的数据就是字符串类型数据的时候,那么你就使用StringRedisTemplate即可。
但是如果你的数据是复杂的对象类型,而取出的时候又不想做任何的数据转换,直接从Redis里面取出一个对象,那么使用RedisTemplate
redis服务类:
public class redisTemplate
{
@Autowired
private RedisTemplate<String,String> redisTemplate;
public void add(String key,Long time,User user){
Gson gson = new Gson();
redisTemplate.opsForValue().set(key,gson.toJson(user),time, TimeUnit.MINUTES);
}
public void add(String key,Long time,List<User> users){
Gson gson = new Gson();
redisTemplate.opsForValue().set(key,gson.toJson(users),time,TimeUnit.MINUTES);
}
public User get(String key){
Gson gson = new Gson();
User user = null;
String userJson = redisTemplate.opsForValue().get(key);
if(!StringUtils.isEmpty(userJson))
user = gson.fromJson(userJson,User.class);
return user;
}
public List<User> getList(String key){
Gson gson = new Gson();
List<User> list = null;
String listJson = redisTemplate.opsForValue().get(key);
if(!StringUtils.isEmpty(listJson))
list = gson.fromJson(listJson,new TypeToken<List<User>>(){}.getType());
return list;
}
public void delete(String key){
redisTemplate.opsForValue().getOperations().delete(key);
}
}
配置redisConfig来初始化redisTemplate:
springboot中省略了xml配置文件,通过@Configuration和@Bean向spring容器暴露配置信息
@Configuration
public class redisConfig {
@Bean
public RedisTemplate<String,String> redisTemplate(RedisConnectionFactory redisConnectionFactory){
StringRedisTemplate template = new StringRedisTemplate(redisConnectionFactory);//选用了stringRedisTemplate
//使用Jackson2JsonRedisSerializer来序列化和反序列化redis的value值(默认使用JDK的序列化方式)
Jackson2JsonRedisSerializer J2JRS = new Jackson2JsonRedisSerializer(Object.class);
ObjectMapper om = new ObjectMapper();
// 指定要序列化的域,field,get和set,以及修饰符范围,ANY是都有包括private和public
om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
// 指定序列化输入的类型,类必须是非final修饰的,final修饰的类,比如String,Integer等会跑出异常
om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
J2JRS.setObjectMapper(om);
template.setValueSerializer(J2JRS);
template.afterPropertiesSet();
return template;
}
}
测试:
ps (测试前先启动redis服务)
@Autowired redisTemplate rt;
rt.delete(this.getClass().getName());
rt.add(this.getClass().getName(),10L,user);
rt.get(this.getClass().getName());
使用注解的方式调用Redis
除了像上面所述的方法来调用redis,我们还可以使用SpringCache注解的方式来调用redis,更加地方便,代码也会更加简洁。
创建redisCacheConfig类
@Configuration
@EnableCaching
public class RedisCacheConfig extends CachingConfigurerSupport {
protected final static Logger log = LoggerFactory.getLogger(RedisCacheConfig.class);
private volatile JedisConnectionFactory mJedisConnectionFactory;
private volatile RedisTemplate<String, String> mRedisTemplate;
private volatile RedisCacheManager mRedisCacheManager;
public RedisCacheConfig() {
super();
}
public RedisCacheConfig(JedisConnectionFactory mJedisConnectionFactory, RedisTemplate<String, String> mRedisTemplate, RedisCacheManager mRedisCacheManager) {
super();
this.mJedisConnectionFactory = mJedisConnectionFactory;
this.mRedisTemplate = mRedisTemplate;
this.mRedisCacheManager = mRedisCacheManager;
}
public JedisConnectionFactory redisConnectionFactory() {
return mJedisConnectionFactory;
}
public RedisTemplate<String, String> redisTemplate(RedisConnectionFactory cf) {
return mRedisTemplate;
}
//选择redis为默认缓存工具
public CacheManager cacheManager(RedisTemplate<?, ?> redisTemplate) {
return mRedisCacheManager;
}
//key生成策略
@Bean
public KeyGenerator keyGenerator() {
return new KeyGenerator() {
@Override
public Object generate(Object o, Method method, Object... objects) {
StringBuilder sb = new StringBuilder();
sb.append(o.getClass().getName());
sb.append(method.getName());
for (Object obj : objects) {
sb.append(obj.toString());
}
return sb.toString();
}
};
}
}
该类告诉 spring 当前使用的缓存服务为 redis 并自定义了缓存 key 生成的规则。
@Cacheable spring 会在其被调用后将返回值缓存起来,以保证下次利用同样的参数来执行该方法时可以直接从缓存中获取结果,而不需要再次执行该方法。
@CachePut 标注的方法在执行前不会去检查缓存中是否存在之前执行过的结果,而是每次都会执行该方法,并将执行结果以键值对的形式存入指定的缓存中。
@CacheEvict 用来标注在需要清除缓存元素的方法或类上的。