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

Spring Reactive应用客户端报错及响应格式异常排查

Troubleshooting Your Spring Reactive WebClient Streaming Issue

Hey there! Let's break down why your WebClient isn't behaving like curl when connecting to your Spring Reactive streaming endpoint, and what that hex output you're seeing means.

First: What's That Hex Format?

The hex content you're seeing is a symptom of failed JSON parsing. Your server is sending streaming JSON (application/stream+json)—this is newline-delimited JSON (NDJSON), where each second a new JSON object is sent over a single long-lived connection. When your WebClient code tries to parse this continuous stream as a single Custom object (via bodyToMono), it can't handle the sequence of multiple JSON entries. The unparsed raw bytes end up being displayed as hex values instead of properly mapped Custom instances.

Why Your Current Code Isn't Working

Let's walk through the key issues in your client code:

  • while(true) is sending repeated unnecessary requests: This defeats the purpose of reactive streaming! Streaming endpoints are designed to keep one connection open and send data over time, not handle hundreds of rapid-fire requests. This overloads both client and server, leading to incomplete, messy responses.
  • bodyToMono(Custom.class) is wrong for streaming: Mono is built for single-value responses. For a continuous stream of Custom objects, you need Flux—Reactor's type for sequences/streaming data.
  • Missing error handling: You're not subscribing to the error signal, so you're missing critical details about why parsing is failing (which aligns with the error log you referenced).

Fixed WebClient Code

Here's the corrected approach to properly consume your streaming endpoint:

import org.springframework.web.reactive.function.client.WebClient;
import reactor.core.publisher.Flux;
import org.springframework.http.MediaType;

public class StreamingClient {
    public static void main(String[] args) throws InterruptedException {
        WebClient webClient = WebClient.create("http://localhost:8080");

        // Use Flux to handle the continuous streaming response
        Flux<Custom> customStream = webClient.get()
                .uri("/test")
                .accept(MediaType.APPLICATION_STREAM_JSON)
                .retrieve()
                .bodyToFlux(Custom.class); // Flux instead of Mono for streaming

        // Subscribe to the stream: handle each Custom object, errors, and completion
        customStream.subscribe(
                custom -> System.out.println("Received: " + custom),
                error -> System.err.println("Error streaming data: " + error.getMessage()),
                () -> System.out.println("Stream completed successfully")
        );

        // Keep the main thread alive (Reactive code runs on daemon threads by default)
        Thread.currentThread().join();
    }

    // Your Custom class (ensure it matches your server's JSON structure with proper getters/setters)
    static class Custom {
        private String someField;
        private int anotherField;

        // Add getters, setters, and a toString() method
        @Override
        public String toString() {
            return "Custom{someField='" + someField + "', anotherField=" + anotherField + "}";
        }
    }
}

Key Fixes Explained

  1. Switched from Mono to Flux: This tells WebClient to expect a continuous sequence of Custom objects, which aligns perfectly with your server's application/stream+json response type.
  2. Removed the while(true) loop: Now we make one single request that stays open, receiving data as it's sent by the server—this is how reactive streaming is intended to work.
  3. Added error handling: The subscribe block now catches and logs errors, so you'll get clear feedback if there's still a parsing issue (like mismatched fields in your Custom class).
  4. Kept the main thread alive: Reactive code runs on daemon threads, so we need to prevent the main thread from exiting immediately to keep the client running.

Why Curl Works

Curl doesn't care about content type or structure—it just reads raw bytes from the connection and prints them to the terminal. It happily displays each newline-delimited JSON object as it arrives, without needing to parse or map them to a Java class. Your WebClient code failed because it was trying to force a streaming response into a single-object model.

内容的提问来源于stack exchange,提问作者Bilbo Baggins

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.28 06:29:23