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

Spring WebClient发送Content-Type为hex的PUT请求报错解决方案

解决方案

原因分析

Spring 对 HTTP 请求的 Content-Type 会严格遵循 MIME 规范校验,要求格式为 类型/子类型(比如 application/json),而你设置的 "hex" 不符合该规范,因此触发 InvalidMimeTypeException;同时原代码中 bodyValue(0x02) 传递的是整数类型,和 curl 命令中发送的内容(字符串 "02" 或字节 0x02)不匹配。


方案一:绕过 Content-Type 校验,手动写入请求体

如果服务端必须要求 Content-Type 为 "hex",可以使用 BodyInserters.fromCallback 直接写入请求体,避免 Spring 自动解析 Content-Type:

情况1:服务端期望接收 hex 字符串(和 curl -d '02' 行为一致)

WebClient.builder().build()
        .put()
        .uri(this.URL)
        .header("Content-Type", "hex")
        .body(BodyInserters.fromCallback(outputMessage -> {
            // 写入字符串"02"的ASCII字节
            outputMessage.getBody().write(ByteBuffer.wrap("02".getBytes(StandardCharsets.US_ASCII)))
                    .subscribe();
            return Mono.empty();
        }))
        .retrieve()
        .bodyToMono(String.class);

情况2:服务端期望接收原始字节 0x02(hex 对应的二进制数据)

WebClient.builder().build()
        .put()
        .uri(this.URL)
        .header("Content-Type", "hex")
        .body(BodyInserters.fromCallback(outputMessage -> {
            // 写入字节0x02
            outputMessage.getBody().write(ByteBuffer.wrap(new byte[]{0x02}))
                    .subscribe();
            return Mono.empty();
        }))
        .retrieve()
        .bodyToMono(String.class);

方案二:使用标准 MIME 类型(需服务端兼容)

如果服务端可以接受标准 MIME 类型,将 Content-Type 设置为对应类型,同时传递正确的请求体:

传递 hex 字符串

WebClient.builder().build()
        .put()
        .uri(this.URL)
        .contentType(MediaType.TEXT_PLAIN)
        .bodyValue("02")
        .retrieve()
        .bodyToMono(String.class);

传递原始字节

WebClient.builder().build()
        .put()
        .uri(this.URL)
        .contentType(MediaType.APPLICATION_OCTET_STREAM)
        .bodyValue(new byte[]{0x02})
        .retrieve()
        .bodyToMono(String.class);

方案三:自定义支持 "hex" 的编解码器(进阶)

通过配置 WebClient 的编解码器,自定义支持 "hex" 类型的消息写入器,这样可以正常使用 contentType() 和 bodyValue() 方法:

// 构建支持hex类型的WebClient
WebClient webClient = WebClient.builder()
        .codecs(configurer -> {
            configurer.customCodecs().register(new HttpMessageWriter<byte[]>() {
                @Override
                public boolean canWrite(ResolvableType elementType, MediaType mediaType) {
                    return mediaType != null && "hex".equals(mediaType.getType());
                }

                @Override
                public Mono<Void> write(Publisher<? extends byte[]> input, ResolvableType elementType, MediaType mediaType, ReactiveHttpOutputMessage message, Map<String, Object> hints) {
                    return message.writeWith(Mono.from(input).map(ByteBuffer::wrap));
                }

                @Override
                public List<MediaType> getWritableMediaTypes() {
                    return Collections.singletonList(new MediaType("hex"));
                }
            });
        })
        .build();

// 使用该WebClient发送请求
webClient.put()
        .uri(this.URL)
        .contentType(new MediaType("hex"))
        .bodyValue(new byte[]{0x02}) // 若服务端期望字符串则传递"02".getBytes()
        .retrieve()
        .bodyToMono(String.class);

内容的提问来源于stack exchange,提问作者Sourabh Mane

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.27 20:09:51