更改使用JAXWS生成的默认XML名称空间前缀

我正在使用JAXWS为我们正在构建的Java应用程序生成WebService客户端。

当JAXWS构建其XML以在SOAP协议中使用时,它会生成以下名称空间前缀:

     

我的问题是我的对手(一家大型转账公司)管理我的客户端连接的服务器,拒绝接受WebService调用( 请不要问我的原因 ),除非XMLNS(XML namepspace前缀是soapenv )。 喜欢这个:

      

所以我的问题是:

有没有办法命令JAXWS(或任何其他Java WS客户端技术)使用soapenv而不是env作为XMLNS前缀来生成客户端? 是否有API调用来设置此信息?

谢谢!

也许这对你来说已经晚了,我不确定这是否可行,但你可以试试。

首先,您需要实现SoapHandler,并且在handleMessage方法中,您可以修改SOAPMessage 。 我不确定您是否可以直接修改该前缀,但您可以尝试:

 public class MySoapHandler implements SOAPHandler { @Override public boolean handleMessage(SOAPMessageContext soapMessageContext) { try { SOAPMessage message = soapMessageContext.getMessage(); // I haven't tested this message.getSOAPHeader().setPrefix("soapenv"); soapMessageContext.setMessage(message); } catch (SOAPException e) { // Handle exception } return true; } ... } 

然后你需要创建一个HandlerResolver

 public class MyHandlerResolver implements HandlerResolver { @Override public List getHandlerChain(PortInfo portInfo) { List handlerChain = Lists.newArrayList(); Handler soapHandler = new MySoapHandler(); String bindingID = portInfo.getBindingID(); if (bindingID.equals("http://schemas.xmlsoap.org/wsdl/soap/http")) { handlerChain.add(soapHandler); } else if (bindingID.equals("http://java.sun.com/xml/ns/jaxws/2003/05/soap/bindings/HTTP/")) { handlerChain.add(soapHandler); } return handlerChain; } } 

最后,您必须将HandlerResolver添加到客户端服务:

 Service service = Service.create(wsdlLoc, serviceName); service.setHandlerResolver(new MyHandlerResolver()); 

这篇文章虽然对于原版海报来说可能为时已晚,但其目的在于帮助其他可能遇到此问题的人。 我不得不在最近几天解决这个问题。 特别是,我需要更改SOAP信封中使用的前缀,因为服务提供者要求名称空间前缀符合非常特定的模式。 符合此模式需要更改信封,标题和正文以及正文元素的名称空间前缀(来自JAX-WS放置的标准名称)。 以下是我使用的解决方案的概述:

 import javax.xml.namespace.QName; import javax.xml.soap.SOAPBody; import javax.xml.soap.SOAPElement; import javax.xml.soap.SOAPEnvelope; import javax.xml.soap.SOAPException; import javax.xml.soap.SOAPHeader; import javax.xml.soap.SOAPMessage; import javax.xml.ws.handler.MessageContext; import javax.xml.ws.handler.soap.SOAPHandler; import javax.xml.ws.handler.soap.SOAPMessageContext; import java.util.HashSet; import java.util.Iterator; import java.util.Set; public class MyMessageNamespaceMapper implements SOAPHandler { @Override public Set getHeaders() { return null; } @Override public boolean handleMessage(SOAPMessageContext context) { final Boolean outbound = (Boolean) context.get(MessageContext.MESSAGE_OUTBOUND_PROPERTY); // only process outbound messages if (outbound) { try { final SOAPMessage soapMessage = context.getMessage(); final SOAPEnvelope soapEnvelope = soapMessage.getSOAPPart().getEnvelope(); final SOAPHeader soapHeader = soapMessage.getSOAPHeader(); final SOAPBody soapBody = soapMessage.getSOAPBody(); // STEP 1: add new prefix/namespace entries soapEnvelope.addNamespaceDeclaration("S1", "http://schemas.xmlsoap.org/soap/envelope/"); soapEnvelope.addNamespaceDeclaration("FOO-1", "http://foo1.bar.com/ns"); // STEP 2: set desired namespace prefixes // set desired namespace prefix for the envelope, header and body soapEnvelope.setPrefix("S1"); soapHeader.setPrefix("S1"); soapBody.setPrefix("S1"); addDesiredBodyNamespaceEntries(soapBody.getChildElements()); // STEP 3: remove prefix/namespace entries entries added by JAX-WS soapEnvelope.removeNamespaceDeclaration("S"); soapEnvelope.removeNamespaceDeclaration("SOAP-ENV"); removeUndesiredBodyNamespaceEntries(soapBody.getChildElements()); // IMPORTANT! "Save" the changes soapMessage.saveChanges(); } catch (SOAPException e) { // handle the error } } return true; } private void addDesiredBodyNamespaceEntries(Iterator childElements) { while (childElements.hasNext()) { final Object childElementNode = childElements.next(); if (childElementNode instanceof SOAPElement) { SOAPElement soapElement = (SOAPElement) childElementNode; // set desired namespace body element prefix soapElement.setPrefix("FOO-1"); // recursively set desired namespace prefix entries in child elements addDesiredBodyNamespaceEntries(soapElement.getChildElements()); } } } private void removeUndesiredBodyNamespaceEntries(Iterator childElements) { while (childElements.hasNext()) { final Object childElementNode = childElements.next(); if (childElementNode instanceof SOAPElement) { SOAPElement soapElement = (SOAPElement) childElementNode; // we remove any prefix/namespace entries added by JAX-WS in the body element that is not the one we want for (String prefix : getNamespacePrefixList(soapElement.getNamespacePrefixes())) { if (prefix != null && ! "FOO-1".equals(prefix)) { soapElement.removeNamespaceDeclaration(prefix); } } // recursively remove prefix/namespace entries in child elements removeUndesiredBodyNamespaceEntries(soapElement.getChildElements()); } } } private Set getNamespacePrefixList(Iterator namespacePrefixIter) { Set namespacePrefixesSet = new HashSet<>(); while (namespacePrefixIter.hasNext()) { namespacePrefixesSet.add((String) namespacePrefixIter.next()); } return namespacePrefixesSet; } @Override public boolean handleFault(SOAPMessageContext context) { return true; } @Override public void close(MessageContext context) { } } 

在服务类的实例上设置上面的处理程序解析器(由JAX-WS / wsimport生成)如下所示:

 yourWebServiceClient.setHandlerResolver(new HandlerResolver() { @Override public List getHandlerChain(PortInfo portInfo) { return Arrays.asList(new MyMessageNamespaceMapper()); } });