@file:DependsOn("io.projectreactor:reactor-core:3.2.9.RELEASE")
import reactor.core.publisher.*

switchIfEmpty总是被调用的原因

先看一个例子

//打印A,没有打印b,说明调用flatMap,没调用switchIfEmpty
Mono.justOrEmpty<String>("a")
.flatMap({Mono.just(it.uppercase())})
.switchIfEmpty(Mono.just("b"))
.subscribe({println(it)})
reactor.core.publisher.LambdaMonoSubscriber@107f4980
//只打印了b,说明没调用flatMap,调用了switchIfEmpty
Mono.justOrEmpty<String>(null)
.flatMap({Mono.just(it.uppercase())})
.switchIfEmpty(Mono.just("b"))
.subscribe({println(it)})

再看一个例子

//打印flatMap,也打印了switchIfEmpty,说明flatMap和switchIfEmpty都调用了
Mono.justOrEmpty<String>("a")
.flatMap({Mono.fromRunnable<Void>({println("flatMap")})})
.switchIfEmpty({Mono.fromRunnable<Void>({println("switchIfEmpty")})})
.subscribe({println(it)})
flatMap
switchIfEmpty
reactor.core.publisher.LambdaMonoSubscriber@77d680e6
//只打印了switchIfEmpty,说明没调用flatMap,调用了switchIfEmpty
Mono.justOrEmpty<String>(null)
.flatMap({Mono.fromRunnable<Void>({println("flatMap")})})
.switchIfEmpty({Mono.fromRunnable<Void>({println("switchIfEmpty")})})
.subscribe({println(it)})
switchIfEmpty

switchIfEmpty如果上一个操作符的数据类型是Void,则switchIfEmpty会被调用。

怎么解决这个问题

switchIfEmpty上一个操作符的返回值不能是Void,可以使用java.lang.ref.SoftReference或java.util.concurrent.atomic.AtomicReference作为返回值,然后根据SoftReference和AtomicReference的值去判断

改写上面的例子

//这样就只调用了flatMap
Mono.justOrEmpty<String>("a")
.map({java.lang.ref.SoftReference(it)})
.defaultIfEmpty(java.lang.ref.SoftReference(null))
.flatMap({
    if(it.get()==null){
        Mono.fromRunnable<Void>({println("switchIfEmpty")})
    }else{
        Mono.fromRunnable<Void>({println("flatMap")})
.subscribe({println(it)})
flatMap
reactor.core.publisher.LambdaMonoSubscriber@76ddd61a

主要思路就是flatMap+switchIfEmpty的组合改写成map+defaultIfEmpty+flatMap的组合

典型场景:gateway过滤器处理请求

DataBufferUtils.join(request.getBody())
    .map(SoftReference::new)
    .defaultIfEmpty(new SoftReference<>(null))
    .flatMap(new Function<SoftReference<DataBuffer>, Mono<Void>>() {
        @Override
        public Mono<Void> apply(SoftReference<DataBuffer> reference) {
            if(reference.get()==null){
                //无body逻辑
            }else{
                //有body逻辑
    });
				
赠送jar包:sentinel-reactor-adapter-1.8.0.jar; 赠送原API文档:sentinel-reactor-adapter-1.8.0-javadoc.jar; 赠送源代码:sentinel-reactor-adapter-1.8.0-sources.jar; 赠送Maven依赖信息文件:sentinel-reactor-adapter-1.8.0.pom; 包含翻译后的API文档:sentinel-reactor-adapter-1.8.0-javadoc-API文档-中文(简体)-英语-对照版.zip; Maven坐标:com.alibaba.csp:sentinel-reactor-adapter:1.8.0; 标签:alibaba、csp、sentinel、adapter、reactor、jar包、java、中英对照文档; 使用方法:解压翻译后的API文档,用浏览器打开“index.html”文件,即可纵览文档内容。 人性化翻译,文档中的代码和结构保持不变,注释和说明精准翻译,请放心使用。 双语对照,边学技术、边学英语。
switchIfEmpty(Observable emptyObservable)操作符从字面意思上就很好理解,就是当为空的时候跳转到emptyObservable。 那么如何理解当为空的时候. 下面将会使用实际案例解释这个switchIfEmpty的使用方法。 一、业务需求 假如我们的app里有加载文章列表功能,要求加载的逻辑如下:加载文章的的时候,先从本地加载,如果本地存在就是用本地的数据,...
三、RxJava flatMap操作符用法详解 四、RxJava concatMap操作符用法详解 五、RxJava onErrorResumeNext操作符实现app与服务器间token机制 六、RxJava retryWhen操作符... 需求了解: 在使用 Rxjava 开发中,经常有一些各种条件的操作 ,如比较两个 Observable 谁先发射了数据、跳过指定条件的 Observable 等一系列的条件操作需求,那么很幸运, Rxjava 中已经有了很多条件操作符,一起来了解一下吧。 下面列出了一些Rxja... 1、create操作符 创建一个被观察者Observable对象 Observable&amp;lt;String&amp;gt; observable = Observable.create(new ObservableOnSubscribe&amp;lt;String&amp;gt;() { @Override public v...
Reactor响应式编程介绍-1 (学习笔记 2021.11.5) 前言: (中文文档) (官网) 本文档的一些典型的名词如下:Publisher(发布者)、Subscriber(订阅者)、Subscription(订阅 n.)、subscribe(订阅 v.)。 event/signal(事件/信号,原文常甚至在一个句子将两个词来回用,但表示的意思是基本相同的, 因此如果你看到本文翻译有时候用事件,有时候用信号,在本文档内基本可以认为一个意思)。 sequence/stream(序列/流,两个词意思
【已解决】Error running ‘xxx项目’: Command line is too long. Shorten command line for xxx or also for Spring Boot default configuration. 根据错误信息可知,指令太过长,根据提示缩短指令即可。 在IDEA中找到 Run-&amp;amp;amp;gt; Edit Configurations打开:
以下是我为你推荐的几篇关于project-reactor的博客: 1. Reactor 3 Reference Guide:这是官方的指南,详细介绍了Reactor的各种特性,包括Flux、Mono、Schedulers、Operators等等。 2. Getting Started with Reactor 3:这篇博客介绍了Reactor的基本概念和用法,适合初学者入门。 3. Reactive Programming with Project Reactor:这篇博客探讨了Reactor的响应式编程理念和实现,对于理解Reactor的设计思想非常有帮助。 4. Project Reactor: A Reactive Programming Foundation for Java:这是一篇介绍Reactor的文章,讲述了ReactorJava中的应用和优势,适合想要了解ReactorJava中的应用的读者。 5. Reactive Programming with Reactor 3:这篇博客深入探讨了Reactor 3的实现细节和用法,对于有一定经验的开发者非常有帮助。 希望这些资源能帮助你更好地学习project-reactor
spring-Sessions are not supported by the MongoDB cluster to which this client is connected 为啥我按照你的方式,还是有这个错。 Caused by: java.lang.NullPointerException: null at java.base@17.0.5/sun.net.dns.ResolverConfigurationImpl.stringToList(ResolverConfigurationImpl.java:69) ~[na:na] at java.base@17.0.5/sun.net.dns.ResolverConfigurationImpl.loadConfig(ResolverConfigurationImpl.java:136) ~[na:na] at java.base@17.0.5/sun.net.dns.ResolverConfigurationImpl.nameservers(ResolverConfigurationImpl.java:159) ~[na:na] at jdk.naming.dns@17.0.5/com.sun.jndi.dns.DnsContextFactory.serversForUrls(DnsContextFactory.java:149) ~[gateway.exe:na] at jdk.naming.dns@17.0.5/com.sun.jndi.dns.DnsContextFactory.getContext(DnsContextFactory.java:81) ~[gateway.exe:na] at jdk.naming.dns@17.0.5/com.sun.jndi.dns.DnsContextFactory.urlToContext(DnsContextFactory.java:120) ~[gateway.exe:na] at jdk.naming.dns@17.0.5/com.sun.jndi.dns.DnsContextFactory.getInitialContext(DnsContextFactory.java:64) ~[gateway.exe:na] at java.naming@17.0.5/javax.naming.spi.NamingMa