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

Spring Integration中HttpRequestExecutingMessageHandler ContentType覆盖问题求助

解决Spring Integration HttpRequestExecutingMessageHandler的Content-Type问题

你的问题核心是HttpRequestExecutingMessageHandler没有正确设置请求的Content-Type为application/json,导致目标REST接口拒绝请求。我们先分析你代码里的问题,再给出几种可行的解决方案:


问题分析

你在配置DefaultHttpHeaderMapper时的逻辑有误:

HeaderMapper<HttpHeaders> mapper = new DefaultHttpHeaderMapper();
HttpHeaders httpHeaders = new HttpHeaders();
httpHeaders.add(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE);
mapper.toHeaders(httpHeaders);

这段代码只是把HttpHeaders转换为MessageHeaders,但并没有告诉HeaderMapper要将消息中的Content-Type头传递到HTTP请求里,也没有给HttpRequestExecutingMessageHandler设置默认的Content-Type。


解决方案

方法1:直接给HttpRequestExecutingMessageHandler设置默认Content-Type(最推荐)

如果你的目标接口固定只接受application/json,这是最简单的方式——直接调用handler的setContentType方法,无需处理消息头或HeaderMapper:

@Bean
@ServiceActivator(inputChannel = "httpRequestOutChannel")
public HttpRequestExecutingMessageHandler outbound() {
    HttpRequestExecutingMessageHandler handler = new HttpRequestExecutingMessageHandler(documentConverterRestUrl);
    handler.setHttpMethod(HttpMethod.POST);
    handler.setErrorHandler(httpResponseErrorHandler);
    handler.setExpectedResponseType(String.class);
    handler.setCharset(Charset.defaultCharset().name());
    
    // 直接设置请求的Content-Type
    handler.setContentType(MediaType.APPLICATION_JSON_VALUE);
    
    handler.setOutputChannel(httpResponseChannel());
    return handler;
}

这种方式会强制所有通过该handler发送的请求使用application/json作为Content-Type,无需修改消息转换的代码。

方法2:配置HeaderMapper传递消息中的Content-Type头

如果你需要根据不同消息动态设置Content-Type,可以在消息转换时添加Content-Type头,再配置HeaderMapper将这个头传递到HTTP请求:

首先修改transformRequest方法,给消息添加Content-Type头:

@ServiceActivator(inputChannel = "transformRequestToJsonChannel", outputChannel = "httpRequestOutChannel")
public Message<?> transformRequest(Message<DocumentConverterRequest> message) {
    LOG.info("transforming document converter request to json: '{}'", message.getPayload());
    ObjectToJsonTransformer transformer = new ObjectToJsonTransformer();
    transformer.setContentType(MediaType.APPLICATION_JSON_UTF8_VALUE);
    Object payload = transformer.transform(message).getPayload();
    LOG.info("payload: '{}'", payload.toString());
    
    // 给消息添加Content-Type头
    return MessageBuilder.withPayload(payload)
            .setHeader(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_UTF8_VALUE)
            .build();
}

然后正确配置DefaultHttpHeaderMapper,让它传递这个头:

@Bean
@ServiceActivator(inputChannel = "httpRequestOutChannel")
public HttpRequestExecutingMessageHandler outbound() {
    HttpRequestExecutingMessageHandler handler = new HttpRequestExecutingMessageHandler(documentConverterRestUrl);
    handler.setHttpMethod(HttpMethod.POST);
    handler.setErrorHandler(httpResponseErrorHandler);
    handler.setExpectedResponseType(String.class);
    handler.setCharset(Charset.defaultCharset().name());
    
    // 配置HeaderMapper传递Content-Type头
    DefaultHttpHeaderMapper headerMapper = (DefaultHttpHeaderMapper) DefaultHttpHeaderMapper.outboundMapper();
    // 指定要传递的出站HTTP头(这里只需要Content-Type)
    headerMapper.setOutboundHeaderNames(new String[]{HttpHeaders.CONTENT_TYPE});
    // 如果你需要传递所有标准请求头,可以用:
    // headerMapper.setOutboundHeaderNames(DefaultHttpHeaderMapper.STANDARD_REQUEST_HEADERS);
    
    handler.setHeaderMapper(headerMapper);
    handler.setOutputChannel(httpResponseChannel());
    return handler;
}

方法3:利用ObjectToJsonTransformer的自动头设置

其实ObjectToJsonTransformer在设置contentType后,会自动给转换后的消息添加对应的Content-Type头,你可以简化transformRequest方法:

@ServiceActivator(inputChannel = "transformRequestToJsonChannel", outputChannel = "httpRequestOutChannel")
public Message<?> transformRequest(Message<DocumentConverterRequest> message) {
    LOG.info("transforming document converter request to json: '{}'", message.getPayload());
    ObjectToJsonTransformer transformer = new ObjectToJsonTransformer();
    transformer.setContentType(MediaType.APPLICATION_JSON_UTF8_VALUE);
    // 直接返回转换后的消息,它已经带有Content-Type头
    Message<?> transformedMessage = transformer.transform(message);
    LOG.info("payload: '{}'", transformedMessage.getPayload().toString());
    return transformedMessage;
}

然后再配合方法2中的HeaderMapper配置,就能正确传递Content-Type到HTTP请求。


总结

  • 如果接口固定接受JSON,优先使用方法1,代码最简洁;
  • 如果需要动态设置Content-Type,选择方法2+方法3的组合,让消息携带头信息并通过HeaderMapper传递。

内容的提问来源于stack exchange,提问作者Anton Styopin

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.14 08:03:54