如何在Spring SOAP WebService中修改请求命名空间URI?
问题描述
多个遗留系统调用同一个@Endpoint,但每个系统使用不同的命名空间——除SOAP Body首个子元素的命名空间不同外,请求负载、实现逻辑及功能完全一致。需要在请求到达@Endpoint之前,将传入SOAP请求的命名空间替换为通用命名空间,曾尝试EndpointInterceptor但未找到替换命名空间的有效方法。
遗留系统1请求示例
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"> <soapenv:Header/> <soapenv:Body> <GetRecordsRequest xmlns="http://www.test.com/system1"> <maxRecords>100</maxRecords> </GetRecordsRequest> </soapenv:Body> </soapenv:Envelope>
遗留系统2请求示例
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"> <soapenv:Header/> <soapenv:Body> <GetRecordsRequest xmlns="http://www.abctest.com/system2"> <maxRecords>100</maxRecords> </GetRecordsRequest> </soapenv:Body> </soapenv:Envelope>
解决方案
可以通过自定义SOAP消息转换器或改进EndpointInterceptor实现命名空间替换,以下是具体实现方案:
方法一:自定义SoapMessageConverter
Spring WS中SoapMessageConverter负责SOAP消息与Java对象的转换,重写其fromMessage方法即可在转换前修改命名空间:
- 实现自定义转换器类:
public class NamespaceReplacingSoapMessageConverter extends SaajSoapMessageConverter { // 定义业务通用的目标命名空间 private static final String TARGET_NAMESPACE = "http://your/common/namespace"; @Override protected Object fromMessage(SoapMessage message, Object parameterType) throws IOException { Node bodyContent = message.getSoapBody().getFirstChild(); if (bodyContent instanceof Element) { Element requestElement = (Element) bodyContent; // 替换当前元素的命名空间 requestElement.setNamespaceURI(TARGET_NAMESPACE); // 递归替换所有子元素的命名空间(按需选择,若子元素无需替换可删除此步骤) replaceChildNamespaces(requestElement, TARGET_NAMESPACE); } return super.fromMessage(message, parameterType); } private void replaceChildNamespaces(Element parent, String targetNamespace) { NodeList children = parent.getChildNodes(); for (int i = 0; i < children.getLength(); i++) { Node node = children.item(i); if (node instanceof Element) { Element childElement = (Element) node; childElement.setNamespaceURI(targetNamespace); replaceChildNamespaces(childElement, targetNamespace); } } } }
- 在Spring配置中注册该转换器:
@Configuration @EnableWs public class WebServiceConfig extends WsConfigurerAdapter { @Override public void configureMessageConverters(List<MessageConverter> converters) { converters.add(new NamespaceReplacingSoapMessageConverter()); super.configureMessageConverters(converters); } }
方法二:改进EndpointInterceptor实现
EndpointInterceptor本身可以修改SOAP消息,关键是获取可编辑的SOAP消息对象:
- 实现自定义拦截器:
public class NamespaceReplacingInterceptor implements EndpointInterceptor { private static final String TARGET_NAMESPACE = "http://your/common/namespace"; @Override public boolean handleRequest(MessageContext messageContext, Object endpoint) throws Exception { SoapMessage soapMessage = (SoapMessage) messageContext.getRequest(); Element bodyElement = (Element) soapMessage.getSoapBody().getFirstChild(); if (bodyElement != null) { bodyElement.setNamespaceURI(TARGET_NAMESPACE); // 按需递归替换子元素命名空间 replaceChildNamespaces(bodyElement, TARGET_NAMESPACE); } return true; } private void replaceChildNamespaces(Element parent, String targetNamespace) { NodeList children = parent.getChildNodes(); for (int i = 0; i < children.getLength(); i++) { Node node = children.item(i); if (node instanceof Element) { Element child = (Element) node; child.setNamespaceURI(targetNamespace); replaceChildNamespaces(child, targetNamespace); } } } @Override public boolean handleResponse(MessageContext messageContext, Object endpoint) throws Exception { return true; } @Override public boolean handleFault(MessageContext messageContext, Object endpoint) throws Exception { return true; } @Override public void afterCompletion(MessageContext messageContext, Object endpoint, Exception ex) throws Exception { // 空实现即可 } }
- 注册拦截器到Spring WS配置:
@Configuration @EnableWs public class WebServiceConfig extends WsConfigurerAdapter { @Override public void addInterceptors(List<EndpointInterceptor> interceptors) { interceptors.add(new NamespaceReplacingInterceptor()); super.addInterceptors(interceptors); } }
注意事项
- 若仅需替换Body首个子元素的命名空间,可删除递归替换子元素的代码;
- 确保
TARGET_NAMESPACE与@Endpoint中@PayloadRoot注解指定的命名空间一致; - 测试时需验证修改后的SOAP消息能否被正确解析为对应的Java对象。
内容的提问来源于stack exchange,提问作者Rayyan
相关产品推荐
相关产品推荐

