SpringBoot集成Redis详解(附带实例)
Spring Boot 提供了集成 Redis 的组件包 spring-boot-starter-data-redis,能够非常方便地集成到项目中。
spring-boot-starter-data-redis 组件主要依赖 spring-data-redis 和 lettuce 库。Spring Boot 1.0 默认使用的是 Jedis 客户端,Spring Boot 2.0 版本之后改为 Lettuce 客户端。
虽然 Lettuce 与 Jedis 都是连接 Redis 的客户端程序,但是两者在实现上还是有些不同的:
因此,Spring Boot 2.0 之后将之前的 Jedis 改成了 Lettuce。
Spring Boot 提供的 Redis 组件 spring-boot-starter-data-redis 也是基于 Spring Data 封装的,它们之间的依赖关系如下图所示:

图 1 spring-boot-starter-data-redis 组件的依赖关系
如图 1 所示,spring-boot-starter-data-redis 和 Spring Data Redis 两者是包含与被包含的关系,或者说前者更好地封装了后者:
与 JdbcTemplate 类似,RedisTemplate 是 Spring 针对 Redis 封装的一个比较强大的模板,以方便使用。只要在所需的地方注入 RedisTemplate 即可,无须其他额外配置,开箱即用。
RedisTemplate 有两个方法经常用到:opsForXXX() 和 boundXXXOps(),XXX 是 value(值) 的数据类型:
它们的使用特别简单,在调用类中注入 RedisTemplate,操作哪种类型的数据就调用其对应的 Operations(操作)。调用示例如下:
当然,RedisTemplate 也提供了 DefaultValueOperations 对象操作字符串类型数据,比如 set()、get()、incr() 等方法。调用这些方法可以方便地存储任意的 Java 类型,而无须进行数据的序列化和反序列化操作。
例如,我们在某个类或方法中需要反复操作某个特定的 key 中的数据,则可以先定义对应的 BoundKeyOperations,然后使用此类重复操作 key 中的数据,无须再调用方法中指定的 key。示例代码如下:
下面通过示例演示如何在 Spring Boot 项目中集成 Redis:
首先创建单元测试类,注入 RedisTemplate,然后调用 set() 方法写入缓存数据来测试 Redis 是否集成成功。
缓存数据的修改也特别简单,重新调用 set() 方法即可,Redis 会判断 key 是否存在,若存在则更新缓存的数据。
单击 Run Test 或在方法上右击,选择 Run 'testString',运行单元测试方法,结果如下图所示:

图 2 testString 单元测试的运行结果
结果表明创建的单元测试运行成功,我们使用 RedisTemplate 成功创建并读取缓存数据。同时也说明 Spring Boot 项目成功集成 Redis。
下面通过示例演示 Redis 常用操作。
首先,创建 User 实体类,示例代码如下:
然后,创建 TestRedisTemplate 单元测试,添加读取、创建缓存的测试方法。示例代码如下:
最后,单击 Run Test 或在方法上右击,选择 Run 'testString',运行单元测试方法,结果如下图所示。

图 3 testObj单元测试的运行结果
结果表明创建的单元测试运行成功,我们使用 RedisTemplate 成功创建并读取缓存数据。同时也说明 Spring Boot 项目成功集成 Redis。
下面我们来测试如何删除缓存,示例代码如下:

图 4 testDelete单元测试的运行结果
下面创建一个 User 对象,将 user 数据存入 Redis 并设置 10 秒后缓存失效,然后判断数据是否存在并打印结果。

图 5 testString单元测试的运行结果
结果表明 Redis 缓存中已经不存在之前插入的数据,这说明该数据已经过期并被删除。在这种测试方法中可以使用 hasKey() 方法判断 key 是否存在。
spring-boot-starter-data-redis 组件主要依赖 spring-data-redis 和 lettuce 库。Spring Boot 1.0 默认使用的是 Jedis 客户端,Spring Boot 2.0 版本之后改为 Lettuce 客户端。
虽然 Lettuce 与 Jedis 都是连接 Redis 的客户端程序,但是两者在实现上还是有些不同的:
- Jedis 在实现上直连 Redis 服务器,在多线程环境下是非线程安全的,除非使用连接池为每个 Jedis 实例增加物理连接。
- Lettuce 基于 Netty 的连接实例(StatefulRedisConnection)可以在多个线程间并发访问,并且是线程安全的,它支持多线程环境下的并发访问,同时也是可伸缩的设计,在一个连接实例不够的情况下可以按需增加连接实例。
因此,Spring Boot 2.0 之后将之前的 Jedis 改成了 Lettuce。
Spring Boot 提供的 Redis 组件 spring-boot-starter-data-redis 也是基于 Spring Data 封装的,它们之间的依赖关系如下图所示:

图 1 spring-boot-starter-data-redis 组件的依赖关系
如图 1 所示,spring-boot-starter-data-redis 和 Spring Data Redis 两者是包含与被包含的关系,或者说前者更好地封装了后者:
- Lettuce:可伸缩的 Redis 客户端,基于 Netty NIO 框架来有效地管理多个连接。
- Spring Data Redis:Spring Data 项目中的模块,封装了多个 Redis 客户端,让开发者对 Redis 的操作更加高效便捷。
- Spring Data:Spring 框架中的重要组成部分,它极大地简化了构建基于 Spring 框架应用的数据操作,包括非关系数据库、Map-Reduce 框架、云数据服务等,同时也支持关系数据库。
- spring-boot-starter-data-redis:Spring Boot 提供的 Redis 集成启动器(Starter),依赖于 spring-data-redis 和 lettuce 库。
RedisTemplate
前面介绍了 Spring Boot 提供的 Redis 组件 spring-boot-starter-data-redis,其中重要的是 RedisTemplate。与 JdbcTemplate 类似,RedisTemplate 是 Spring 针对 Redis 封装的一个比较强大的模板,以方便使用。只要在所需的地方注入 RedisTemplate 即可,无须其他额外配置,开箱即用。
RedisTemplate 有两个方法经常用到:opsForXXX() 和 boundXXXOps(),XXX 是 value(值) 的数据类型:
- opsForXXX 获取到一个操作(Operation),但是没有指定操作的 key(键),可以在一个连接(事务)内操作多个 key 以及对应的 value;
- boundXXXOps 获取到一个指定 key 的操作,在一个连接内只操作这个 key 对应的 value。
1) RedisTemplate操作
RedisTemplate 针对 Redis 的 String、List、Hash、Set、ZSet 五种数据类型提供了下面五个基本类来操作对应的数据类型:- ValueOperations:针对 String 类型,实现简单的键-值操作;
- SetOperations:针对 Set 类型的数据操作;
- ZSetOperations:针对 ZSet 类型的数据操作;
- HashOperations:针对 Hash 类型的数据操作;
- ListOperations:针对 List 类型的数据操作。
它们的使用特别简单,在调用类中注入 RedisTemplate,操作哪种类型的数据就调用其对应的 Operations(操作)。调用示例如下:
// 操作String类型 redisTemplate.opsForValue().set("key","value"); // 操作Hash类型 redisTemplate.opsForHash().put("hash","test","hello"); // 操作List redisTemplate.opsForList().leftPush("list","weiz"); // 操作Set redisTemplate.opsForSet().add("set","weiz") // 操作ZSet redisTemplate.opsForZSet().add("zset","weiz");通过上面的示例,如果要操作 String 类型的数据,则调用 redisTemplate.opsForValue() 方法获取 ValueOperations 实例,最后调用 set() 或 get() 方法即可。
当然,RedisTemplate 也提供了 DefaultValueOperations 对象操作字符串类型数据,比如 set()、get()、incr() 等方法。调用这些方法可以方便地存储任意的 Java 类型,而无须进行数据的序列化和反序列化操作。
2) BoundValueOperations
RedisTemplate 提供了 API 用于对 key 执行 bound(绑定)便捷化操作,可以通过 bound 封装指定的 key,然后执行一系列的操作,而无须显式地再次指定 key,即 BoundKeyOperations 将事务操作封装,由容器控制:- BoundValueOperations 是针对 String 类型的绑定操作;
- BoundSetOperations 是针对 Set 类型的绑定操作;
- BoundListOperations 是针对 List 类型的绑定操作;
- BoundZSetOperations 是针对 ZSet 类型的绑定操作;
- BoundHashOperations 是针对 Hash 类型的绑定操作。
例如,我们在某个类或方法中需要反复操作某个特定的 key 中的数据,则可以先定义对应的 BoundKeyOperations,然后使用此类重复操作 key 中的数据,无须再调用方法中指定的 key。示例代码如下:
String key = "weiz"; // 获取Redis对value的操作对象,需要先设置key BoundValueOperations boundTemplate = redisTemplate.boundValueOps(key); boundTemplate.set("bound test"); // 获取value String value = boundTemplate.get();通过上面的示例,首先定义 key 为“weiz”的 BoundValueOperations 实例,然后在后续的操作中直接使用定义的 boundTemplate 实例,操作这个 key 对应的数据,无须在调用方法中指定 key。
Spring Boot项目中实现Redis数据缓存
Spring Boot 项目集成 Redis 非常简单,只需在项目中增加 spring-boot-starter-data-redis 的依赖。下面通过示例演示如何在 Spring Boot 项目中集成 Redis:
1) 引入Redis依赖包
在 pom.xml 中增加 spring-boot-starter-data-redis 的依赖:<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-redis</artifactId> </dependency>
2) 修改配置文件
在 application.properties 配置文件增加有关 Redis 的配置:# Redis 数据库(默认为 0) spring.redis.database=0 # Redis 服务器地址 spring.redis.host=127.0.0.1 # Redis 服务器连接端口 spring.redis.port=6379 # Redis 服务器连接密码(默认为空) spring.redis.password= # 连接池最大连接数(使用负值表示没有限制),默认为8 spring.redis.jedis.pool.max-active=8 # 连接池最大阻塞等待时间(使用负值表示没有限制),默认为-1 spring.redis.jedis.pool.max-wait=-1 # 连接池中的最大空闲连接,默认为10 spring.redis.jedis.pool.max-idle=10 # 连接池中的最小空闲连接,默认为0 spring.redis.jedis.pool.min-idle=2 # 超时时间 spring.redis.timeout=6000上面的示例配置中,最主要的就是 Redis 的连接配置,其他的属性都可以使用默认值。
3) 验证测试
配置完成之后,Redis 就集成到项目中了。接下来测试 Redis 是否配置成功。首先创建单元测试类,注入 RedisTemplate,然后调用 set() 方法写入缓存数据来测试 Redis 是否集成成功。
@SpringBootTest public class TestRedisTemplate { @Autowired private RedisTemplate redisTemplate; @Test public void testString() { // 调用set()方法创建缓存 redisTemplate.opsForValue().set("hello:redis", "hello spring boot"); System.out.println("hello redis: "+ redisTemplate.opsForValue().get("hello:redis")); } }在上面的例子中,我们使用 redisTemplate 的 set() 方法缓存了字符串数据“hello spring boot”,然后调用 get() 方法获取该缓存数据,从而验证数据是否缓存成功。
缓存数据的修改也特别简单,重新调用 set() 方法即可,Redis 会判断 key 是否存在,若存在则更新缓存的数据。
单击 Run Test 或在方法上右击,选择 Run 'testString',运行单元测试方法,结果如下图所示:

图 2 testString 单元测试的运行结果
结果表明创建的单元测试运行成功,我们使用 RedisTemplate 成功创建并读取缓存数据。同时也说明 Spring Boot 项目成功集成 Redis。
Redis缓存的常用操作
在实际项目中,对 Redis 缓存的常用操作是:创建与读取缓存数据、删除缓存数据、缓存超时等。下面通过示例演示 Redis 常用操作。
1) 创建与读取缓存数据
对于常用的缓存数据的创建与读取操作,调用 RedisTemplate 中的 set()、get() 方法即可。下面通过示例演示人员信息的缓存创建与读取。首先,创建 User 实体类,示例代码如下:
@public class User implements Serializable { private String name; @JsonIgnore private String password; private Integer age; @JsonFormat(pattern = "yyyy-MM-dd hh:mm:ss",locale = "zh",timezone = "GMT+8") private Date birthday; @JsonInclude(JsonInclude.Include.NON_NULL) private String desc; //省略get、set }在上面的示例中,我们定义了一个普通的 User 实体类。需要注意的是,Redis 缓存整个实体类对象就需要继承 Serializable 可序列化接口。
然后,创建 TestRedisTemplate 单元测试,添加读取、创建缓存的测试方法。示例代码如下:
@Test public void testObj(){ User user=new User(); user.setName("weiz"); user.setPassword("123456"); user.setAge(30); ValueOperations<String, User> operations=redisTemplate.opsForValue(); // 调用set()方法创建缓存 operations.set("user:weiz", user); // 调用get()方法获取数据 User u=operations.get("user:weiz"); System.out.println("name: "+u.getName()+",u.age:"+u.getAge()); }在上面的例子中,调用 redisTemplate 类的 set() 方法存储用户对象数据,存储成功后通过 get() 方法获取该缓存数据。
最后,单击 Run Test 或在方法上右击,选择 Run 'testString',运行单元测试方法,结果如下图所示。

图 3 testObj单元测试的运行结果
结果表明创建的单元测试运行成功,我们使用 RedisTemplate 成功创建并读取缓存数据。同时也说明 Spring Boot 项目成功集成 Redis。
2) 删除缓存数据
有时需要把过期或者没用的缓存数据删除,应该如何实现呢?RedisTemplate 提供了 delete() 方法来删除过期的缓存 key。下面我们来测试如何删除缓存,示例代码如下:
@Test public void testDelete() { ValueOperations<String, User> operations=redisTemplate.opsForValue(); redisTemplate.opsForValue().set("weiz:deletekey", "need delete"); // 删除缓存 redisTemplate.delete("deletekey"); // 判断key是否存在 boolean exists=redisTemplate.hasKey("deletekey"); if(exists){ System.out.println("exists is true"); }else{ System.out.println("exists is false"); } }在上面的示例中,首先创建缓存 weiz:deletekey,然后删除此 key 来判断数据是否存在。如下图所示,输出结果表明缓存的 key 和对应的 value 字符串已经被成功删除。

图 4 testDelete单元测试的运行结果
3) 缓存超时失效
Redis 可以对存入数据设置缓存超时时间,超过缓存时间 Redis 就会自动删除该数据。这种特性非常适合有时效限制的数据缓存及删除的场景。下面创建一个 User 对象,将 user 数据存入 Redis 并设置 10 秒后缓存失效,然后判断数据是否存在并打印结果。
@Test public void testExpire() throws InterruptedException { User user=new User(); user.setName("weiz expire"); user.setAge(30); ValueOperations<String, User> operations=redisTemplate.opsForValue(); // 创建缓存并设置缓存失效时间 operations.set("weiz:expire", user,10000, TimeUnit.MILLISECONDS); Thread.sleep(5000); // 10秒后判断缓存是否存在 boolean exists=redisTemplate.hasKey("weiz:expire"); if(exists){ System.out.println("exists is true"); }else{ System.out.println("exists is false"); } Thread.sleep(10000); // 10秒后判断缓存是否存在 exists=redisTemplate.hasKey("weiz:expire"); if(exists){ System.out.println("exists is true"); }else{ System.out.println("exists is false"); } }单击 Run Test 或在方法上右击,选择 Run 'testExpire',运行单元测试方法,结果如下图所示。

图 5 testString单元测试的运行结果
结果表明 Redis 缓存中已经不存在之前插入的数据,这说明该数据已经过期并被删除。在这种测试方法中可以使用 hasKey() 方法判断 key 是否存在。
相关文章
- SpringBoot集成RabbitMQ详解(附带实例)
- SpringBoot是什么?SpringBoot的优缺点有哪些?
- SpringBoot URL映射详解(附带实例)
- SpringBoot @PathVariable实现参数传递(附带实例)
- SpringBoot传递参数的5种方法(附带实例)
- SpringBoot @Scheduled定时任务详解(附带实例)
- SpringBoot Cron表达式的用法(新手必看)
- SpringBoot @Scheduled实现定时任务(附带实例)
- SpringBoot实现RabbitMQ简单队列(附带实例)
- SpringBoot是什么,SpringBoot简介(新手必看)