定义Redis工具类

2,311 阅读4分钟

「这是我参与11月更文挑战的第26天,活动详情查看:2021最后一次更文挑战

通过上一篇文章的学习:SpringBoot中集成Redis,已经对Redis在SpringBoot中的使用有了初步的认识,可以使用RedisTemplate对象进行缓存数据的处理。

但是,在实际项目开发中使用Redis的地方很多,每次使用都要注入RedisTemplate对象的话属实麻烦,且SpringBoot提供的RedisTemplate类中功能较多,不应该暴露在太多地方,可以根据项目开发需要自定义合适的Redis工具类进行使用。

1. RedisTemplate操作Redis

SpringBoot中集成Redis后,使用了如下的方式来测试Redis是否可用:

@Test
public void testRedis(){
    ValueOperations<String, String> operations = redisTemplate.opsForValue();
    operations.set("name", "tom");
    System.out.println(operations.get("name"));
}

其中,ValueOperations<K, V>类作SpringBoot为Redis数据定义的类,在RestTemplate中还定义了其他相似的类来满足Redis中不同的数据类型的需要。

image-20211128111033226

其中包含有:

  • ValueOperations:操作简单的字符串K-V
  • ListOperations:处理list类型的数据
  • HashOperations:处理hash类型的数据
  • SetOperations:处理set类型数据
  • ZSetOperations:处理zset类型数据

除了使用opsForValue()方法获取对应的ValueOperations<K, V>对象并设置对应的键和值外,还可以使用链式方法restTemplate.boundValueOps("name").append("tom")来设置缓存数据。

对RedisTemplate类对象中的数据处理方法简单了解后,就可以在此基础上进行Redis工具类的封装了。

2. Redis工具类基本功能

根据项目中的功能需求程度,定义一个基本的Redis工具类需要提供功能有:

  • 数据的放入和获取
  • 数据的存在判断逻辑
  • 数据有效期设置
  • 数据失效处理
  • 数据的删除
  • 其他如缓存长度、所有key值等方法

其中,数据的放入、获取等需要根据Redis中不同的数据结构类型实现不同的逻辑,而针对缓存key的操作可以进行统一处理。

3. 工具类实现

工具类定义主要就是在RedisTemplate类对象的基础上进行封装,只需要在此处注入对象,其他地方使用时直接调用工具类中对应方法即可。

3.1 工具类的结构实现

新增一个RedisUtil工具类,其中定义Redis操作相关方法,并使用@Component作为Spring容器组件,保证可以注入并使用RedisTemplate对象。

//Redis工具类
@Component
public final class RedisUtil{
    @Autowired
    private RedisTemplate<String, Object> redisTemplate;
    
    //使用redisTemplate实现数据操作
    ...
}

3.2 缓存数据的放入和获取

处理Redis数据时,最基本的功能莫过于在缓存中存放和获取数据,并根据缓存需要设置有效时间,针对Redis中不同的数据结构需要实现不同的逻辑。

  • String数据结构,最简单的键值对
  • list数据结构,字符串的集合,存放多个字符串
  • hash数据结构,key-value结构的集合信息,需要额外的对key的操作
  • set数据结构,不重复的字符串的集合结构,或者有序的zset结构

对于最简单的键值对,数据作为字符串被放入Redis中,只需要调用redisTemplate对象中的opsForValue()获取到字符串操作对象,并讲字符串数据放入Redis中,获取时根据指定key返回字符串即可。

//String类型数据的放入和获取
public boolean set(String key, Object value) {
    try {
        redisTemplate.opsForValue().set(key, value);
        return true;
    } catch (Exception e) {
        e.printStackTrace();
        return false;
    }
}
public boolean set(String key, Object value, long time) {
    try {
        if (time > 0) {
            redisTemplate.opsForValue().set(key, value, time, TimeUnit.SECONDS);
        } else {
            set(key, value);
        }
        return true;
    } catch (Exception e) {
        e.printStackTrace();
        return false;
    }
}
public Object get(String key) {
    return key == null ? null : redisTemplate.opsForValue().get(key);
}

而对于hash类型的数据,因为数据类型是一个包含多组key-value的集合,因此不仅需要针对Redis中的key进行处理,还需要对hash集合中的key提供查询、增加、删除等功能逻辑。

//hash数据的放入、获取等操作
public boolean hset(String key, Map<String, Object> map) {
    try {
        redisTemplate.opsForHash().putAll(key, map);
        return true;
    } catch (Exception e) {
        e.printStackTrace();
        return false;
    }
}
public boolean hset(String key, Map<String, Object> map, long time) {
    try {
        redisTemplate.opsForHash().putAll(key, map);
        if (time > 0) {
            expire(key, time);
        }
        return true;
    } catch (Exception e) {
        e.printStackTrace();
        return false;
    }
}
public Map<Object, Object> hget(String key) {
    return redisTemplate.opsForHash().entries(key);
}
//针对hash中的指定key的操作
public boolean hItemSet(String key, String item, Object value) {
    try {
        redisTemplate.opsForHash().put(key, item, value);
        return true;
    } catch (Exception e) {
        e.printStackTrace();
        return false;
    }
}
public Object hItemGet(String key, String item) {
    return redisTemplate.opsForHash().get(key, item);
}
​
public boolean hItemHas(String key, String item) {
    return redisTemplate.opsForHash().hasKey(key, item);
}
public void hItemDel(String key, Object... item) {
    redisTemplate.opsForHash().delete(key, item);
}

3.3 缓存key的操作处理

无论是哪种数据,在Redis中存放是都需要指定一个最外层的redis_key,并以此作为存放和获取的标志,Redis中的key是唯一存在的,对于一些过期、删除、查找等操作可以直接操作key完成。

  • 设置key过期时间
  • 查看指定key过期时间
  • 判断缓存key是否存在
  • 删除指定key
//设置指定key缓存有效期
public boolean expire(String key, long time) {
    try {
        if (time > 0) {
            redisTemplate.expire(key, time, TimeUnit.SECONDS);
        }
        return true;
    } catch (Exception e) {
        e.printStackTrace();
        return false;
    }
}
​
//获取指定key的有效期
public long getExpire(String key) {
    return redisTemplate.getExpire(key, TimeUnit.SECONDS);
}
​
//判断指定key在缓存中是否存在
public boolean hasKey(String key) {
    try {
        return redisTemplate.hasKey(key);
    } catch (Exception e) {
        e.printStackTrace();
        return false;
    }
}
​
//删除指定key
@SuppressWarnings("unchecked")
public void del(String... key) {
    if (key != null && key.length > 0) {
        if (key.length == 1) {
            redisTemplate.delete(key[0]);
        } else {
            redisTemplate.delete(Arrays.asList(key));
        }
    }
}