Spring Boot 2.0 WebClient如何在流水线中提前处理404错误
处理WebFlux API流水线中的404错误
看起来你在Spring WebFlux的链式调用里遇到了类型不匹配的问题——当你尝试在flatMap里处理404状态码时,后续的map操作期望的是Mono类型,但你的处理逻辑可能打破了这个响应式类型链。别担心,这里有两种靠谱的解决方案:
方案一:用onStatus直接拦截404状态码
这是最简洁的方式,WebClient的onStatus方法可以专门针对特定状态码做拦截,直接抛出Spring的ResponseStatusException,框架会自动帮你转换成对应的HTTP响应:
@PostMapping(path = ["/customers/{customerId}/place"]) fun create(@PathVariable customerId: String): Mono<ResponseEntity<OrderPlacedResponse>> { return webClient .get() .uri("/{customerId}/cart", customerId) // 用占位符写法更规范 .retrieve() // 用retrieve替代exchange,简化响应处理 .onStatus(HttpStatus.NOT_FOUND::equals) { _ -> Mono.error(ResponseStatusException(HttpStatus.NOT_FOUND, "Customer $customerId not found")) } .bodyToMono(Cart::class.java) // 假设Cart是你接收的购物车实体类 .flatMap { cart -> // 这里编写你的下单逻辑,比如生成订单、转换响应 val orderResponse = OrderPlacedResponse(/* 填充响应参数 */) Mono.just(ResponseEntity.ok(orderResponse)) } }
为什么这个方案可行?
retrieve()会自动处理2xx状态码,非2xx的异常状态可以通过onStatus精准拦截- 捕获到404时直接用
Mono.error()抛出异常,会终止整个流水线,后续操作不会执行,完美符合你“遇到404就终止并返回404”的需求
方案二:如果必须保留exchange()处理响应
如果你因为某些业务需求要使用exchange(),可以用exchangeToMono来确保整个流程的类型一致性:
@PostMapping(path = ["/customers/{customerId}/place"]) fun create(@PathVariable customerId: String): Mono<ResponseEntity<OrderPlacedResponse>> { return webClient .get() .uri("/{customerId}/cart", customerId) .exchangeToMono { response -> if (response.statusCode() == HttpStatus.NOT_FOUND) { Mono.error(ResponseStatusException(HttpStatus.NOT_FOUND, "Customer $customerId not found")) } else { response.bodyToMono(Cart::class.java) .flatMap { cart -> // 处理下单逻辑 val orderResponse = OrderPlacedResponse(/* 填充响应参数 */) Mono.just(ResponseEntity.ok(orderResponse)) } } } }
关键注意点
- 用
exchangeToMono替代exchange().flatMap(),它强制要求返回Mono类型,从根源避免了类型不匹配问题 - 无论状态码是否为404,都要确保返回的是
Mono:404时返回Mono.error(),正常情况返回处理后的Mono<ResponseEntity<...>>
你之前的编译失败大概率是因为在flatMap里没有正确用Mono包裹处理结果——比如直接抛出普通异常而非Mono.error(),或者返回了非Mono类型的对象,导致后续操作的类型链断裂。上面两种方案都严格遵循了WebFlux的响应式编程规范,应该能解决你的问题。
内容的提问来源于stack exchange,提问作者Chirdeep Tomar




