2023-09-08 20:27:44
在Spring WebFlux中处理响应式流中的null值并抛出自定义异常时,需遵循Reactive Streams规范(禁止null元素),推荐使用flatMap或handle操作符实现条件性错误处理,而非依赖switchIfEmpty或filter。
问题根源:Reactive Streams对null值的限制switchIfEmpty:仅处理上游流未发出任何元素(直接完成)的情况,无法检测map发出的null元素。
filter(Objects::nonNull):虽能过滤null,但违反规范(map已发出null),且switchIfEmpty仍需流为空时才触发,无法针对单个null元素抛异常。
flatMap将每个元素映射为一个新的Publisher(如Mono),允许根据条件返回不同流(含值或错误)。
示例代码:
import org.springframework.security.core.context.ReactiveSecurityContextHolder;import org.springframework.security.core.context.SecurityContext;import reactor.core.publisher.Mono;public class PrincipalService { public Mono<String> getUserPrincipalNameSafely() { return ReactiveSecurityContextHolder.getContext() .map(SecurityContext::getAuthentication) .map(authentication -> (UserAuthenticationToken) authentication) .flatMap(token -> { String principalName = token.getUserPrincipalName(); if (principalName == null) { return Mono.error(new MissingPrincipalException("Missing email field in the JWT token")); } else { return Mono.just(principalName); } }); }}关键点:
handle通过BiConsumer接收元素和SynchronousSink,支持发出值、过滤或错误信号,适合复杂逻辑。
示例代码:
import org.springframework.security.core.context.ReactiveSecurityContextHolder;import org.springframework.security.core.context.SecurityContext;import reactor.core.publisher.Mono;import reactor.core.publisher.SynchronousSink;public class PrincipalService { public Mono<String> getUserPrincipalNameSafelyWithHandle() { return ReactiveSecurityContextHolder.getContext() .map(SecurityContext::getAuthentication) .map(authentication -> (UserAuthenticationToken) authentication) .handle((token, sink) -> { String principalName = token.getUserPrincipalName(); if (principalName == null) { sink.error(new MissingPrincipalException("Missing email field in the JWT token")); } else { sink.next(principalName); } }); }}关键点:
flatMap:适合简单条件分支(如null检查),代码更简洁。
handle:适合复杂逻辑(如多条件过滤、转换或错误)。
推荐选择: