首页 > 编程笔记 > Java笔记 阅读:2

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 两者是包含与被包含的关系,或者说前者更好地封装了后者:

RedisTemplate

前面介绍了 Spring Boot 提供的 Redis 组件 spring-boot-starter-data-redis,其中重要的是 RedisTemplate。

与 JdbcTemplate 类似,RedisTemplate 是 Spring 针对 Redis 封装的一个比较强大的模板,以方便使用。只要在所需的地方注入 RedisTemplate 即可,无须其他额外配置,开箱即用。

RedisTemplate 有两个方法经常用到:opsForXXX() 和 boundXXXOps(),XXX 是 value(值) 的数据类型:

1) RedisTemplate操作

RedisTemplate 针对 Redis 的 String、List、Hash、Set、ZSet 五种数据类型提供了下面五个基本类来操作对应的数据类型:
它们的使用特别简单,在调用类中注入 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 将事务操作封装,由容器控制:
例如,我们在某个类或方法中需要反复操作某个特定的 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 是否存在。

相关文章