You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Spring WebFlux WebClient返回200时出现UnsupportedOperationException异常排查

问题原因

你遇到的异常核心原因是Server-Sent Events(SSE)格式的响应只能被读取为Flux,而非Mono:

  • 机场服务的验证接口通过produces = MediaType.TEXT_EVENT_STREAM_VALUE声明输出SSE流式响应,Spring会使用ServerSentEventHttpMessageReader处理这种响应格式,而该阅读器明确不支持将SSE流读取为单个Mono对象。
  • 尽管你的接口返回的是Mono<Boolean>,但SSE格式要求响应是一个事件流——即使只有一个事件,客户端也必须以流的方式接收。而你在WebClient中调用bodyToMono(Boolean.class),强制要求将流转为单个对象,触发了不支持的操作异常。

解决方法

根据实际需求,有两种修复方案:

方案1:改用普通JSON响应(推荐,你的场景不需要流式输出)

修改机场服务控制器

把接口的produces改为普通JSON格式,或直接去掉该属性(Spring WebFlux默认输出JSON):

@RestController
@RequestMapping("/v1/airports")
@AllArgsConstructor
public class AirportsController {
    private static final List<String> validCodes = List.of("MLG","ROM");
    @GetMapping(value = "/validate/{airportCode}") // 移除produces,或改为produces = MediaType.APPLICATION_JSON_VALUE
    @Operation(description = "Indicates if the airport code is valid or not")
    @ResponseStatus(HttpStatus.OK)
    public Mono<Boolean> validateAirportCode(@PathVariable String airportCode){
        if(validCodes.contains( airportCode )){
            return Mono.just( true ).log();
        }else {
            return Mono.just( false ).log();
        }
    }
}

修改WebClient客户端

去掉指定TEXT_EVENT_STREAM_VALUE的accept设置,让客户端接收JSON响应:

@Component
@AllArgsConstructor
public class AirportsWebClient {
    public Mono<Boolean> validateAirportCode(String airportCode){
        WebClient airportsWebClient = WebClient.builder().baseUrl( "http://localhost:8082" ).build();
        return airportsWebClient.get()
                .uri( "/v1/airports/validate/" + airportCode )
                // 移除accept(TEXT_EVENT_STREAM_VALUE),或改为accept(MediaType.APPLICATION_JSON_VALUE)
                .retrieve()
                .bodyToMono( Boolean.class );
    }
}

方案2:保留SSE格式,调整客户端接收方式

如果确实需要使用SSE格式(比如后续要扩展为流式输出),则客户端需要将响应读取为Flux,再通过next()获取第一个事件转为Mono:

@Component
@AllArgsConstructor
public class AirportsWebClient {
    public Mono<Boolean> validateAirportCode(String airportCode){
        WebClient airportsWebClient = WebClient.builder().baseUrl( "http://localhost:8082" ).build();
        return airportsWebClient.get()
                .uri( "/v1/airports/validate/" + airportCode )
                .accept( MediaType.valueOf( MediaType.TEXT_EVENT_STREAM_VALUE ) )
                .retrieve()
                .bodyToFlux( Boolean.class )
                .next(); // 从流中获取第一个元素转为Mono
    }
}

内容的提问来源于stack exchange,提问作者Gabriel García Garrido

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.24 01:37:10