如何在@ExceptionHandler中访问Mono/Flux的ContextView对象?
在@ExceptionHandler中访问Reactor ContextView的正确方式
是的,在Spring WebFlux环境下,你完全可以在@ExceptionHandler中访问Mono/Flux的ContextView,不过需要注意正确的实现方式,以及确保你的项目是基于WebFlux构建的(WebFlux原生支持在异常处理方法中返回反应式类型)。
正确实现方案
方式1:通过Mono.deferContextual直接访问上下文
调整你的全局异常处理器,确保方法返回Mono<ResponseEntity>,并通过deferContextual获取上下文信息:
import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.ControllerAdvice; import org.springframework.web.bind.annotation.ExceptionHandler; import reactor.core.publisher.Mono; @ControllerAdvice public class GlobalExceptionHandler { private static final Logger logger = LoggerFactory.getLogger(GlobalExceptionHandler.class); @ExceptionHandler(Exception.class) public Mono<ResponseEntity<Object>> handleException(Exception ex) { return Mono.deferContextual(contextView -> { // 从上下文中获取调试信息,添加默认值避免空指针 String debugInfo = contextView.getOrDefault("debug_information", "无调试信息"); logger.info("异常调试信息:{}", debugInfo); return Mono.just(ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).build()); }); } }
方式2:在业务流中提前处理异常(替代全局处理器)
如果全局处理器的上下文传递出现问题,也可以在接口的业务流中通过onErrorResume直接捕获异常并访问上下文:
@RestController class Endpoint { @Autowired private Service service; @GetMapping Mono<ResponseEntity<String>> get() { return service.doStuff() .contextWrite(context -> context.put("debug_information", "XYZ")) .onErrorResume(ex -> Mono.deferContextual(contextView -> { logger.info("异常调试信息:{}", contextView.get("debug_information")); // 直接返回错误响应 return Mono.just(ResponseEntity.status(500).body("服务器内部错误")); })); } }
注意事项
- 确保你的项目依赖的是Spring WebFlux,而非Spring MVC(MVC不支持在
@ExceptionHandler中返回反应式类型)。 - 上下文信息会随着Mono/Flux的订阅链传递,只要异常是在该链中抛出的,上下文就可以被正常访问。
内容的提问来源于stack exchange,提问作者woezelmann
相关产品推荐
相关产品推荐

