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
相关产品推荐
相关产品推荐

