将Mono<Object>转为普通Object遇返回null,求正确实现方法
问题描述
我尝试将Mono<Object>转换为普通的Object,编写了如下代码:
Mono<BasicTokenResponseDto> response = responseMono.map(obj -> { BasicTokenResponseDto tokenResponse = new BasicTokenResponseDto(); tokenResponse.setApi_key(obj.getApi_key()); return tokenResponse; }); // ... AtomicReference<BasicTokenResponseDto> plainJavaObject = new AtomicReference<>(); Mono<BasicTokenResponseDto> tokenMono = clientService.getJwt(); tokenMono.subscribe(transformedToken -> { plainJavaObject.set(transformedToken); }); BasicTokenResponseDto token = plainJavaObject.get(); System.out.println("!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! " + token.getApi_key());
但最终获取到的token值为null,请问该如何正确获取对象的值?
原因分析
问题核心是响应式编程的异步特性:
subscribe是异步执行的主线程不会等待回调完成,就直接执行plainJavaObject.get(),此时AtomicReference还未被赋值,因此拿到null。- 这种通过异步回调赋值、同步取值的方式违背了响应式编程的设计思想,不仅会引发空指针,还可能导致线程阻塞、性能损耗等问题。
正确实现方式
必须遵循响应式编程的链式调用逻辑,通过操作符处理Mono,而非强行将其"拆包"为普通对象:
方式1:链式处理逻辑(推荐)
将所有依赖BasicTokenResponseDto的业务逻辑嵌入响应式调用链中:
clientService.getJwt() .subscribe(transformedToken -> { // 直接在回调内处理对象,比如打印或业务操作 System.out.println("!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! " + transformedToken.getApi_key()); });
如果是在Spring Gateway过滤器这类响应式场景中,需返回Mono让框架处理异步流程:
return clientService.getJwt() .map(token -> { // 示例:将token写入请求头 exchange.getRequest().mutate().header("X-API-KEY", token.getApi_key()).build(); return exchange; }) .then(Mono.defer(() -> chain.filter(exchange)));
方式2:阻塞取值(仅用于非响应式兼容,不推荐)
若必须同步获取值(如遗留非响应式代码),可使用block()方法,但会阻塞当前线程,破坏响应式异步优势:
BasicTokenResponseDto token = clientService.getJwt().block(); if (token != null) { System.out.println("!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! " + token.getApi_key()); }
警告:在WebFlux核心线程池中调用
block()会引发线程阻塞甚至死锁,绝对禁止在响应式环境主线程中使用。
内容的提问来源于stack exchange,提问作者Peter Penzov
相关产品推荐
相关产品推荐

