一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第4天,点击查看活动详情。
昨天简单演示了一下Reactor,今天我们来看看这种方式是怎么操作redis的,操作方法和之前无较大差别,只不过是把原来同步的方式,变为异步执行了而已。、
搞配置
我们要操作redis,所以需要redis的支持,数据是从数据库查的,所以需要jdbc的支持,我们需要导入依赖:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis-reactive</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jdbc</artifactId>
</dependency>
需要指定redis的位置spring.redis.host。
搞代码
我们需要ReactiveStringRedisTemplate的支持,但是并没有提供,因此我们需要自己定义一个
@Bean
ReactiveStringRedisTemplate reactiveRedisTemplate(ReactiveRedisConnectionFactory factory) {
return new ReactiveStringRedisTemplate(factory);
}
我们可以看到这个工厂里面有我们需要的redis的连接。
使用共享锁CountDownLatch,因为我们这个操作是一组,是由两个线程完成的,所以任务数就给1.然后为了看效果,打印一个等待信息。
CountDownLatch cdl = new CountDownLatch(1);
log.info("Waiting");
cdl.await();
查询数据,这个很简单:就是一个函数式接口映射对象
List<Coffee> list = jdbcTemplate.query(
"select * from t_coffee", (rs, i) ->
Coffee.builder()
.id(rs.getLong("id"))
.name(rs.getString("name"))
.price(rs.getLong("price"))
.build()
);
遍历列表,以流的方式并在单线程中执行:
Flux.fromIterable(list)
.publishOn(Schedulers.single())
.doOnComplete(() -> log.info("list ok"))
以流的方式一一映射存入redis中
ReactiveHashOperations<String, String, String> hashOps = redisTemplate.opsForHash()
.flatMap(c -> {
log.info("try to put {},{}", c.getName(), c.getPrice());
return hashOps.put(KEY, c.getName(), c.getPrice().toString());
})
完成之后,打印ok,紧接着设置key的过期时间
.doOnComplete(() -> log.info("set ok"))
.concatWith(redisTemplate.expire(KEY, Duration.ofMinutes(1)))
.doOnComplete(() -> log.info("expire ok"))
然后我们订阅,看订阅是否成功,然后任务完成。
.subscribe(b -> log.info("Boolean: {}", b),
e -> log.error("Exception {}", e.getMessage()),
() -> cdl.countDown());
可以看到这个订阅都是成功的,状态都是正确的。
其实,和我们前面提到的redis使用差不太多,只是另开启了个线程,然后把原来同步的操作变为异步了,就算是响应式编程的简单示例,你学会了吗?