如何为MarshallingWebServiceOutboundGateway添加自定义HTTP请求头?
解决MarshallingWebServiceOutboundGateway添加自定义HTTP请求头的问题
核心原因
MarshallingWebServiceOutboundGateway是SOAP服务网关,它默认的头映射逻辑(DefaultSoapHeaderMapper)仅处理SOAP信封内的头信息,而非HTTP传输层的请求头。你之前的两种尝试(enrichHeaders、重写populateUserDefinedHeader)都是在操作SOAP头,不会影响HTTP请求头。
可行解决方案
方案1:通过WebServiceMessageCallback直接设置HTTP头
在调用网关时,传入请求回调,直接操作SOAP消息的MIME头(对应HTTP请求头),适合需要动态从Integration消息头取值的场景:
@Bean public IntegrationFlow processRequest() { return flow -> flow.channel(INPUT_CHANNEL) .transform(requestMapper, "mapFrom") .handle(webserviceOutboundGateway, e -> e.requestCallback(message -> { if (message instanceof SaajSoapMessage saajMessage) { MimeHeaders mimeHeaders = saajMessage.getSaajMessage().getMimeHeaders(); // 从当前Integration消息头中获取动态值 MessageHeaders headers = MessageContextHolder.get().getHeaders(); mimeHeaders.setHeader(X_TRANSACTION_ID, headers.get(X_TRANSACTION_ID).toString()); mimeHeaders.setHeader(CLIENT_ID, headers.get(CLIENT_ID).toString()); mimeHeaders.setHeader(CLIENT_SECRET, headers.get(CLIENT_SECRET).toString()); } })) .channel(OUTPUT_CHANNEL); }
方案2:自定义ClientInterceptor全局设置HTTP头
创建拦截器,在SOAP请求发送前注入HTTP头,适合全局复用的场景:
public class HttpHeaderInjectingInterceptor implements ClientInterceptor { @Override public boolean handleRequest(MessageContext messageContext) throws WebServiceClientException { if (messageContext.getRequest() instanceof SaajSoapMessage saajMessage) { MimeHeaders mimeHeaders = saajMessage.getSaajMessage().getMimeHeaders(); // 这里可以固定设置值,或者从上下文获取动态值 mimeHeaders.setHeader(X_TRANSACTION_ID, "somevalue"); mimeHeaders.setHeader(CLIENT_ID, "somevalue"); mimeHeaders.setHeader(CLIENT_SECRET, "somevalue"); } return true; } @Override public boolean handleResponse(MessageContext messageContext) { return true; } @Override public boolean handleFault(MessageContext messageContext) { return true; } @Override public void afterCompletion(MessageContext messageContext, Exception ex) {} }
然后在网关配置中添加拦截器:
@Bean public MarshallingWebServiceOutboundGateway muleMLGatewayWebserviceOutboundGateway(...) { MarshallingWebServiceOutboundGateway gateway = ...; gateway.setAdviceChain(Collections.singletonList(muleGatewayFailingAdvice())); // 注入自定义拦截器 gateway.getWebServiceTemplate().setInterceptors(Collections.singletonList(new HttpHeaderInjectingInterceptor())); return gateway; }
方案3:通过HttpComponentsMessageSender全局配置HTTP头
如果使用Apache HttpClient作为传输层,可以自定义消息发送器,全局注入HTTP头:
@Bean public HttpComponentsMessageSender customHttpMessageSender() { HttpComponentsMessageSender sender = new HttpComponentsMessageSender(); sender.setHttpClient(HttpClients.custom() .addInterceptorFirst((HttpRequestInterceptor) (request, context) -> { request.addHeader(X_TRANSACTION_ID, "somevalue"); request.addHeader(CLIENT_ID, "somevalue"); request.addHeader(CLIENT_SECRET, "somevalue"); }) .build()); return sender; } @Bean public MarshallingWebServiceOutboundGateway muleMLGatewayWebserviceOutboundGateway(...) { MarshallingWebServiceOutboundGateway gateway = ...; gateway.setAdviceChain(Collections.singletonList(muleGatewayFailingAdvice())); gateway.getWebServiceTemplate().setMessageSender(customHttpMessageSender()); return gateway; }
为什么之前的尝试无效?
你重写的DefaultSoapHeaderMapper.populateUserDefinedHeader方法,作用是将Integration消息头映射到SOAP信封的<Header>节点中,这些头是SOAP协议层面的,不会被转换为HTTP请求头。要操作HTTP传输层的头,必须直接干预SOAP消息的MIME头或者传输客户端的配置。
内容的提问来源于stack exchange,提问作者Viktor
相关产品推荐
相关产品推荐

