一、什么是Project Reactor
由表及里学 ProjectReactor http://blog.yannxia.top/2018/06/26/java/spring/projectreactor/
即 响应式编程。主要解决了回调地狱(callback hell)的问题。
二、如何使用
1. 引入依赖
<dependency>
<groupId>io.projectreactor</groupId>
<artifactId>reactor-core</artifactId>
</dependency>
2. 例子
@Override
public void run(ApplicationArguments args) throws Exception {
Flux.range(1, 6)
.doOnRequest(n -> log.info("Request {} number", n)) // 注意顺序造成的区别
.publishOn(Schedulers.elastic())
.doOnComplete(() -> log.info("Publisher COMPLETE 1"))
.map(i -> {
log.info("Publish thread: {}, i: {}", Thread.currentThread(), i);
// return i / (3 - i);
return i;
})
// .onErrorReturn(-1) // onErrorReturn 和 onErrorResume 顺序,在前优先
.onErrorResume(e -> {
log.error("ErrorResume: {}", e.toString());
return Mono.just(-2);
})
.doOnComplete(() -> log.info("Publisher COMPLETE 2"))
.subscribeOn(Schedulers.elastic())
.subscribe(i -> log.info("Subscribe thread: {}, i: {}", Thread.currentThread(), i)
,e -> log.error("error: {}", e.toString())
,() -> log.info("Subscriber COMPLETE")
// ,s -> s.request(4)
);
Thread.sleep(2000);
}
二、redis with reactive
1. 引入依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis-reactive</artifactId>
</dependency>
2. 例子
private void reactiveRedis() throws InterruptedException {
ReactiveHashOperations<String, String, String> opsForHash = redisTemplate.opsForHash();
String KEY = "reactor-redis";
CountDownLatch countDownLatch = new CountDownLatch(1);
Flux.fromArray(new String[] {"123", "456"})
.publishOn(Schedulers.single())
.doOnComplete(() -> log.info("list ok"))
.flatMap(c -> {
log.info("try to put {}: {}", c, c);
return opsForHash.put(KEY, c, c);
})
.doOnComplete(() -> log.info("set ok"))
.concatWith(redisTemplate.expire(KEY, Duration.ofMinutes(1)))
.doOnComplete(() -> log.info("expire ok"))
.onErrorResume(e -> {
log.error("exception {}", e.getMessage());
return Mono.just(false);
})
.subscribe(b -> log.info("subscribe: {}", b)
,
e -> log.error("Exception {}", e.getMessage())
,
() -> countDownLatch.countDown()
);
;
countDownLatch.await();
}
三、mongodb with reactive
1. 引入依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-mongodb-reactive</artifactId>
</dependency>
2. 例子
private void reactiveMongo() throws InterruptedException {
CountDownLatch cdl = new CountDownLatch(2);
List<Coffee> objectsToSave = Arrays.asList(new Coffee().setName("猫屎咖啡").setPrice(19).setCreateTime(new Date()).setUpdateTime(new Date()),
new Coffee().setName("拿铁咖啡").setPrice(15).setCreateTime(new Date()).setUpdateTime(new Date()));
mongoTemplate.insertAll(objectsToSave)
.publishOn(Schedulers.elastic())
.doOnNext(c -> log.info("Next: {}", c))
.doOnComplete(() -> {
log.info("Runnable");
mongoTemplate.updateMulti(Query.query(Criteria.where("price").gte(16)),
new Update().inc("price", -5)
.currentDate("updateTime"),
Coffee.class)
.doFinally(s -> {
cdl.countDown();
log.info("Finnally 2, {}", s);
})
.subscribe(r -> log.info("Result is {}", r));
})
.doFinally(s -> {
cdl.countDown();
log.info("Finnally 1, {}", s);
})
.count()
.subscribe(c -> log.info("Insert {} records", c));
cdl.await();
}