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

Spring WebFlux:如何用真实WebClient复现DataBufferLimitException?

可以用真实WebClient复现DataBufferLimitException异常

完全可以用真实WebClient复现这个异常,之前出现WebClientRequestException(连接拒绝)是因为测试时没有启动对应的服务端来返回响应数据。只要在测试中搭建一个临时的服务端(返回指定大小的响应),再配合配置了小缓冲区的WebClient,就能精准复现场景。

实现步骤与示例代码

1. 搭建临时测试服务端

你可以通过两种方式快速搭建服务端:

方式一:使用Spring WebFlux测试切片(@WebFluxTest)

先定义一个测试用的Controller,返回指定大小的字节数据:

@RestController
public class LargeResponseController {
    @GetMapping("/large-data")
    public Mono<DataBuffer> largeData(@RequestParam int size) {
        DataBuffer buffer = DefaultDataBufferFactory.sharedInstance.allocateBuffer(size);
        buffer.write(new byte[size]);
        return Mono.just(buffer);
    }
}

然后编写测试类,启动这个Controller并配置小缓冲区的WebClient:

@WebFluxTest(LargeResponseController.class)
class DataBufferLimitExceptionTest {

    @LocalServerPort
    private int port;

    private WebClient smallBufferWebClient;

    @BeforeEach
    void setUp() {
        // 配置仅1KB缓冲区的WebClient
        smallBufferWebClient = WebClient.builder()
                .baseUrl("http://localhost:" + port)
                .codecs(configurer -> configurer.defaultCodecs()
                        .maxInMemorySize(1024 * 1)) // 对应你问题中的1024*bufferSize
                .build();
    }

    @Test
    void whenResponseExceedsBuffer_throwsDataBufferLimitException() {
        // 请求1025字节的响应,超过缓冲区限制
        Assertions.assertThrows(DataBufferLimitException.class, () -> {
            smallBufferWebClient.get()
                    .uri("/large-data?size=1025")
                    .retrieve()
                    .bodyToMono(Void.class)
                    .block();
        });
    }

    @Test
    void whenResponseWithinBuffer_returns200() {
        ResponseEntity<Void> response = smallBufferWebClient.get()
                .uri("/large-data?size=1024")
                .retrieve()
                .toBodilessEntity()
                .block();

        Assertions.assertEquals(HttpStatus.OK, response.getStatusCode());
    }
}
方式二:手动启动Reactor Netty临时服务器

如果不想依赖Spring的测试上下文,可以直接用Reactor Netty搭建轻量服务端:

class DataBufferLimitExceptionManualTest {

    private HttpServer server;
    private String baseUrl;

    @BeforeEach
    void setUp() {
        // 启动随机端口的Netty服务器
        server = HttpServer.create()
                .port(0)
                .route(routes -> routes
                        .get("/large-data", (req, res) -> {
                            int size = Integer.parseInt(req.param("size").orElse("0"));
                            DataBuffer buffer = DefaultDataBufferFactory.sharedInstance.allocateBuffer(size);
                            buffer.write(new byte[size]);
                            return res.send(Mono.just(buffer));
                        }))
                .bindNow();

        baseUrl = "http://localhost:" + server.port();
    }

    @AfterEach
    void tearDown() {
        server.disposeNow(); // 测试结束关闭服务器
    }

    @Test
    void testBufferLimitScenarios() {
        WebClient smallBufferWebClient = WebClient.builder()
                .baseUrl(baseUrl)
                .codecs(configurer -> configurer.defaultCodecs().maxInMemorySize(1024))
                .build();

        // 验证超限场景
        Assertions.assertThrows(DataBufferLimitException.class, () -> {
            smallBufferWebClient.get()
                    .uri("/large-data?size=1025")
                    .retrieve()
                    .bodyToMono(Void.class)
                    .block();
        });

        // 验证正常场景
        ResponseEntity<Void> okResponse = smallBufferWebClient.get()
                .uri("/large-data?size=512")
                .retrieve()
                .toBodilessEntity()
                .block();
        Assertions.assertEquals(HttpStatus.OK, okResponse.getStatusCode());
    }
}

关键说明

  • 连接拒绝问题的根源:测试时没有启动服务端,WebClient请求的地址无效。上述两种方式都会在测试生命周期内启动临时服务端,解决连接问题。
  • 缓冲区配置:通过maxInMemorySize设置WebClient的最大内存缓冲区,对应你问题中的1024*bufferSize,调整该值即可模拟不同的限制场景。

内容的提问来源于stack exchange,提问作者Maxim Kozlyuk

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.26 09:27:03