SpringBoot整合Redis 之 StringRedisTemplate、RedisTemplate 基础

Spring Boot Data(数据) Redis 中提供了 RedisTemplate StringRedisTemplate

StringRedisTemplateRedisTemplate 的子类,两个方法基本一致,不同之处在于 操作的数据类型不同

  • RedisTemplate 两个泛型都是 Object,意味着存储的 key 和 value 都可以是一个对象
  • StringRedisTemplate 两个泛型都是 String,意味着存储的 的 key 和 value 都只能是字符串。

注:使用 RedisTemplate 默认是将对象序列化到 Redis 中,所以 放入的对象必须实现对象序列化接口

注:两者的 数据是不共通的;也就是说 StringRedisTemplate 只能管理 StringRedisTemplate 里面的数据,RedisTemplate 只能管理 RedisTemplate 中的数据。

环境准备

引入依赖

<dependency>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>

配置文件

# 连接有redis服务的主机
spring.redis.host=localhost 
spring.redis.port=6379
spring.redis.database=0

StringRedisTemplate 基本使用

API 是学不完的,掌握一些基本操作,其他操作有需要再查询即可!

StringRedisTemplate.opsForValue();	// 操作字符串
StringRedisTemplate.opsForHash(); 	// 操作hash
StringRedisTemplate.opsForList(); 	// 操作list
StringRedisTemplate.opsForSet();  // 操作set
StringRedisTemplate.opsForZSet(); 	// 操作有序set

通过@Autowired注解的方式注入 StringRedisTemplate 对象:

@Autowired
private StringRedisTemplate stringRedisTemplate;  // key, value 都是字符串

Key 常用操作

删除一个 key:

stringRedisTemplate.delete("name"); // 删除一个key

删除当前 redis 库中所有键值对:

// 删除当前redis库中所有键值对
Set<String> keys = stringRedisTemplate.keys("*"); // 查询出所有的键
stringRedisTemplate.delete(keys);

判断某个 key 是否存在,判断 key 所对应值的类型:

Boolean hasKey = stringRedisTemplate.hasKey("name"); // 判断某个key是否存在
DataType type = stringRedisTemplate.type("name"); // 判断key对应的值的类型

获取 key 超时时间(-1 永不超时,-2 key不存在,>=0 过期时间)

Long expire = stringRedisTemplate.getExpire("name");

在 redis 中随机获取一个 key:

String randomKey = stringRedisTemplate.randomKey();

修改 key 的名字,要求 key 必须存在,不存在则抛出异常:

stringRedisTemplate.rename("name", "newname");
// stringRedisTemplate.renameIfAbsent("age", "newname");

将指定 key 移动到 指定库:

stringRedisTemplate.move("newname", 1); 

String 常用操作

所有字符串的操作都是通过 StringRedisTemplate.opsForValue(); 实现。

设置一个 key value:

stringRedisTemplate.opsForValue().set("name", "振宇"); // set 用来设置一个key value

获取一个 key 对应 value:

String value = stringRedisTemplate.opsForValue().get("name");

设置一个 key 超时时间

// key:code  value:2537  超时时间:120s 
stringRedisTemplate.opsForValue().set("code", "2537", 120, TimeUnit.SECONDS); 

往指定键的值后面 追加 字符串:

stringRedisTemplate.opsForValue().append("name", "他是一个好人!");

List 常用操作

所有 List 的操作都是通过 StringRedisTemplate.opsForList(); 实现。

从左边往列表中放入一个元素:

stringRedisTemplate.opsForList().leftPush("lists", "振宇");

从左边往列表中放入多个元素(两种方法):

stringRedisTemplate.opsForList().leftPushAll("lists", "张三", "李四", "王五");
List<String> names = new ArrayList<>();
names.add("xiaoming");
names.add("xiaosan");
stringRedisTemplate.opsForList().leftPushAll("lists", names);

遍历整个 List:

List<String> stringList = stringRedisTemplate.opsForList().range("lists", 0, -1);// 遍历list
stringList.forEach(v -> System.out.println("value = " + v));

保留截取的指定区间的 List:

stringRedisTemplate.opsForList().trim("lists", 1, 3);

Set 常用操作

所有 Set 的操作都是通过 StringRedisTemplate.opsForSet(); 实现。

创建 Set 并放入多个元素:

stringRedisTemplate.opsForSet().add("sets", "张三", "张三", "李四", "振宇"); // 创建set 并放入多个元素

查看 Set 中所有成员:

Set<String> sets = stringRedisTemplate.opsForSet().members("sets");
sets.forEach(value -> System.out.println("value = " + value));

获取 Set 中元素个数:

Long size = stringRedisTemplate.opsForSet().size("sets");

ZSet 常用操作

所有 ZSet 的操作都是通过 StringRedisTemplate.opsForZSet(); 实现。

创建 ZSet 并放入元素:

stringRedisTemplate.opsForZSet().add("zsets", "小黑", 20);

指定范围进行查询:

// 遍历所有元素
Set<String> zsets = stringRedisTemplate.opsForZSet().range("zsets", 0, -1);
zsets.forEach(value-> System.out.println(value));

获取指定元素以及分数(可以指定分数范围):

// 获取分数范围在 0 -1000 之间的元素 并排序
Set<ZSetOperations.TypedTuple<String>> zsets1 = stringRedisTemplate.opsForZSet().rangeByScoreWithScores("zsets", 0, 1000);
zsets1.forEach(typedTuple ->{
	System.out.println("value = " + typedTuple.getValue() + ", score = " + typedTuple.getScore());
});

Hash 常用操作

所有 Hash 的操作都是通过 StringRedisTemplate.opsForHash(); 实现。

往指定 Hash 中放入一个 key,value:

stringRedisTemplate.opsForHash().put("maps", "name", "zhangsan");

往指定 Hash 中放入多个 key,value:

 Map<String, String> map = new HashMap<>();
map.put("age", "12");
map.put("bir", "2012-12-12");
stringRedisTemplate.opsForHash().putAll("maps", map); // 放入多个key, value

获取指定 Hash 中某个 key 的 value:

String value = (String) stringRedisTemplate.opsForHash().get("maps", "name");

获取指定 Hash 中多个 key 的 value:

List<Object> values = stringRedisTemplate.opsForHash().multiGet("maps", Arrays.asList("name", "age"));
values.forEach(value -> System.out.println(value));

获取指定 Hash 中所有 key,获取所有 value:

Set<Object> keys = stringRedisTemplate.opsForHash().keys("maps"); // 获取所有keys
List<Object> vals = stringRedisTemplate.opsForHash().values("maps"); // 获取所有values

Key 的绑定操作 Bound

Spring Data 为了方便我们对 redis 进行更友好的操作,提供了 bound api 简化操作。

如果日后对某一个 key 的操作极其频繁,可以将这个 key 绑定到对应 redistemplate 中,可以简化操作。

  • boundValueOps 用来对 String 值绑定 key
  • boundListOps 用来对 List 值绑定 key
  • boundSetOps 用来对 Set 值绑定 key
  • boundZSetOps 用来对 ZSet 值绑定 key
  • boundHashOps 用来对 Hash 值绑定 key

原本代码可能需要这么写:

stringRedisTemplate.opsForValue().set("name", "zhangsan");
stringRedisTemplate.opsForValue().append("name", "是一个好人");
String s = stringRedisTemplate.opsForValue().get("name");
System.out.println(s);

绑定后只需要这么写:

BoundValueOperations<String, String> nameValueOperations = stringRedisTemplate.boundValueOps("name");

nameValueOperations.set("zhangsan");
nameValueOperations.append("是一个好人");
String name = nameValueOperations.get();

对 List 进行绑定:

BoundListOperations<String, String> listsOperations = stringRedisTemplate.boundListOps("lists");
listsOperations.leftPushAll("张三", "李四", "小陈");
List<String> lists = listsOperations.range(0, -1);
lists.forEach(list-> System.out.println(list));

redis 中每个数据类型都可以进行绑定,与上面同理。

RedisTemplate 基本使用

RedisTemplate 的用法和 StringRedisTemplate 基本一样,我们关注他们的不同之处!

RedisTemplateStringRedisTemplate 的区别主要在于他们使用的序列化类:

  • RedisTemplate 使用的是 JdkSerializationRedisSerializer,存入数据时,会将数据先序列化成字节数组,然后再存入 Redis 数据库。;
  • StringRedisTemplate 使用的是 StringRedisSerializer

通过@Autowired注解的方式注入 RedisTemplate 对象:

@Autowired
private RedisTemplate redisTemplate;  //存储对象

想要存入 redis 的对象必须实现序列化接口:

@Data
@AllArgsConstructor
@NoArgsConstructor
@Accessors(chain = true)
public class User implements Serializable { // 实现序列化接口
    private String id;
    private String name;
    private Integer age;
    private Date bir;
}

RedisTemplate 基本操作

往 redis 中存入一个 User 对象:

redisTemplate.setValueSerializer(new JdkSerializationRedisSerializer()); // 指定值使用对象序列化
// 往redis中存入一个User对象
redisTemplate.opsForValue().set("user", new User("21", "小黑", 23, new Date()));
// 根据值获取存入的User对象
User user = (User) redisTemplate.opsForValue().get("user");
System.out.println(user);

需要注意的是,如果通过 redis 客户端查看其中的数据,无法正常显示 key 名,如下图:
在这里插入图片描述
在这里插入图片描述

RedisTemplate 正常往 redis 中存入 String 数据与 StringRedisTemplate 用法几乎一样,但是如果存放的是 String 类型数据则更推荐 StringRedisTemplate 而不是 RedisTemplate

redisTemplate.opsForList().leftPushAll("lists", "hello", "world");
List lists = redisTemplate.opsForList().range("lists", 0, -1);
lists.forEach(list -> System.out.println(list));

RedisTemplate 与 StringRedisTemplate 数据互不相通

RedisTemplate 和 StringRedisTemplate 的数据是不相通的!

1、StringRedisTemplate 往 redis 中存入一个 String 类型的值,分别尝试获取值:

  • RedisTemplate 无法获取到;
  • StringRedisTemplate 可以获取到;
stringRedisTemplate.opsForValue().set("name", "zhenyu");

Object name1 = redisTemplate.opsForValue().get("name");
System.out.println(name1); // null

String name2 = stringRedisTemplate.opsForValue().get("name");
System.out.println(name2); // zhenyu

注:如果是在客户端中操作,视为使用 StringRedisTemplate

2、RedisBuilder 往 redis 中存入一个 User 对象,分别尝试获取值:

  • RedisTemplate 可以获取到;
  • StringRedisTemplate 无法获取到;
redisTemplate.opsForValue().set("user", new User("21", "zhenyu", 23, new Date()));

User user1 = (User) redisTemplate.opsForValue().get("user");
System.out.println(user1); // User(id=21, name=zhenyu, age=23, bir=Sat Jul 04 10:17:12 CST 2020)

String user2 = stringRedisTemplate.opsForValue().get("user");
System.out.println(user2); // null

3、RedisTemplate 往 redis 中存入一个 String 类型的值,分别尝试获取值:

  • RedisTemplate 可以获取到;
  • StringRedisTemplate 无法获取到;
redisTemplate.opsForValue().set("name", "hello");

Object name1 = redisTemplate.opsForValue().get("name");
System.out.println(name1); // hello

String name2 = stringRedisTemplate.opsForValue().get("name");
System.out.println(name2); // null

Redis 应用场景

上面我们学习的只是 StringRedisTemplateRedisTemplate 的基础操作,Redis 真正实现的功能都是建立在这些基础上的,企业中 Redis 的应用场景主要有:

  1. 利用 Redis 中字符串类型完成 手机验证码存储 的实现;
  2. 利用 Redis 中字符串类型完成 具有失效性业务功能,例如淘宝的订单失效时间…
  3. 利用 Redis 实现分布式集群系统中 Session共享
  4. 利用 Redis 中 ZSet 类型(可排序的 Set 类型)实现 排行榜功能sales(zset) [商品id,商品销量]
  5. 利用 Redis 实现 分布式缓存
  6. 利用 Redis 存储认证之后 token 信息,例如微信小程序开发中获取的令牌可能会超时…
  7. 利用 Redis 解决分布式集群系统中分布式锁问题
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章