java 如何更改 Spring-WS 的“SOAP-ENV”默认前缀
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/39242197/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to change "SOAP-ENV" default prefix of Spring-WS
提问by attomos
I've created a web service using Spring-WS.
To maintain compatibility with the old system, I need to change namespace prefix from SOAP-ENV
to soap
.
我已经使用 Spring-WS 创建了一个 Web 服务。为了保持与旧系统的兼容性,我需要将命名空间前缀从 更改SOAP-ENV
为soap
。
I know that SOAP-ENV
and soap
are just namespace prefixes.
As long as they refer to the correct namespace ("http://schemas.xmlsoap.org/soap/envelope/"
), it should be fine.
我知道,SOAP-ENV
和soap
只是命名空间前缀。只要它们引用正确的命名空间 ( "http://schemas.xmlsoap.org/soap/envelope/"
),就应该没问题。
But the old system hard coded the parser code to expect only soap
namespace prefix.
但是旧系统将解析器代码硬编码为仅期望soap
命名空间前缀。
Current response:
当前响应:
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/">
<SOAP-ENV:Header/>
<SOAP-ENV:Body>
...
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>
Expected response:
预期回应:
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
<soap:Header/>
<soap:Body>
...
</soap:Body>
</soap:Envelope>
Here's what I've tried so far
这是我迄今为止尝试过的
Create
EndpointInterceptorAdapter
subclass. This will intercept SOAP response/fault and alter the SOAP envelope. This works, but it's not ideal in terms of performance.public class CustomEndpointInterceptor extends EndpointInterceptorAdapter { private static final String DEFAULT_NS = "xmlns:SOAP-ENV"; private static final String SOAP_ENV_NAMESPACE = "http://schemas.xmlsoap.org/soap/envelope/"; private static final String PREFERRED_PREFIX = "soap"; private static final String HEADER_LOCAL_NAME = "Header"; private static final String BODY_LOCAL_NAME = "Body"; private static final String FAULT_LOCAL_NAME = "Fault"; @Override public boolean handleResponse(MessageContext messageContext, Object endpoint) throws Exception { SaajSoapMessage soapResponse = (SaajSoapMessage) messageContext.getResponse(); alterSoapEnvelope(soapResponse); return super.handleResponse(messageContext, endpoint); } @Override public boolean handleFault(MessageContext messageContext, Object endpoint) throws Exception { SaajSoapMessage soapResponse = (SaajSoapMessage) messageContext.getResponse(); alterSoapEnvelope(soapResponse); return super.handleFault(messageContext, endpoint); } private void alterSoapEnvelope(SaajSoapMessage soapResponse) { Document doc = soapResponse.getDocument(); Element rootElement = doc.getDocumentElement(); rootElement.setPrefix(PREFERRED_PREFIX); // Remove default SOAP namespace rootElement.removeAttribute(DEFAULT_NS); NodeList headerNodes = doc.getElementsByTagNameNS(SOAP_ENV_NAMESPACE, HEADER_LOCAL_NAME); NodeList bodyNodes = doc.getElementsByTagNameNS(SOAP_ENV_NAMESPACE, BODY_LOCAL_NAME); NodeList faultNodes = doc.getElementsByTagNameNS(SOAP_ENV_NAMESPACE, FAULT_LOCAL_NAME); // Remove Header node. if (headerNodes.getLength() != 0) { rootElement.removeChild(headerNodes.item(0)); } // Change Body's SOAP namespace prefix. if (bodyNodes.getLength() != 0) { Element bodyElement = (Element) bodyNodes.item(0); bodyElement.setPrefix(PREFERRED_PREFIX); } if (faultNodes.getLength() != 0) { Element faultElement = (Element) faultNodes.item(0); faultElement.setPrefix(PREFERRED_PREFIX); } } }
Change
package-info.java
in the package that contain WSDL generated classes. I've successfully done this with my company's namespace prefix, but it doesn't work forSOAP-ENV
prefix.@javax.xml.bind.annotation.XmlSchema(namespace = "http://www.example.com/ns/2008/02/02/webservices/blah", xmlns = { @javax.xml.bind.annotation.XmlNs(namespaceURI = "http://www.example.com/ns/2008/02/02/webservices/blah", prefix = ""), @javax.xml.bind.annotation.XmlNs(namespaceURI = "http://schemas.example.com/ns/2007/10/blah", prefix = "ns2"), @javax.xml.bind.annotation.XmlNs(namespaceURI = "http://example.com/ns/2007/23/05/blah/fundamental", prefix = "ns3"), @javax.xml.bind.annotation.XmlNs(namespaceURI = "http://schemas.xmlsoap.org/soap/envelope/", prefix = "soap") // doesn't work }, elementFormDefault = javax.xml.bind.annotation.XmlNsForm.QUALIFIED) package com.thomsonreuters.ts.ets.interdayws.soap.webservice;
创建
EndpointInterceptorAdapter
子类。这将拦截 SOAP 响应/错误并更改 SOAP 信封。这有效,但在性能方面并不理想。public class CustomEndpointInterceptor extends EndpointInterceptorAdapter { private static final String DEFAULT_NS = "xmlns:SOAP-ENV"; private static final String SOAP_ENV_NAMESPACE = "http://schemas.xmlsoap.org/soap/envelope/"; private static final String PREFERRED_PREFIX = "soap"; private static final String HEADER_LOCAL_NAME = "Header"; private static final String BODY_LOCAL_NAME = "Body"; private static final String FAULT_LOCAL_NAME = "Fault"; @Override public boolean handleResponse(MessageContext messageContext, Object endpoint) throws Exception { SaajSoapMessage soapResponse = (SaajSoapMessage) messageContext.getResponse(); alterSoapEnvelope(soapResponse); return super.handleResponse(messageContext, endpoint); } @Override public boolean handleFault(MessageContext messageContext, Object endpoint) throws Exception { SaajSoapMessage soapResponse = (SaajSoapMessage) messageContext.getResponse(); alterSoapEnvelope(soapResponse); return super.handleFault(messageContext, endpoint); } private void alterSoapEnvelope(SaajSoapMessage soapResponse) { Document doc = soapResponse.getDocument(); Element rootElement = doc.getDocumentElement(); rootElement.setPrefix(PREFERRED_PREFIX); // Remove default SOAP namespace rootElement.removeAttribute(DEFAULT_NS); NodeList headerNodes = doc.getElementsByTagNameNS(SOAP_ENV_NAMESPACE, HEADER_LOCAL_NAME); NodeList bodyNodes = doc.getElementsByTagNameNS(SOAP_ENV_NAMESPACE, BODY_LOCAL_NAME); NodeList faultNodes = doc.getElementsByTagNameNS(SOAP_ENV_NAMESPACE, FAULT_LOCAL_NAME); // Remove Header node. if (headerNodes.getLength() != 0) { rootElement.removeChild(headerNodes.item(0)); } // Change Body's SOAP namespace prefix. if (bodyNodes.getLength() != 0) { Element bodyElement = (Element) bodyNodes.item(0); bodyElement.setPrefix(PREFERRED_PREFIX); } if (faultNodes.getLength() != 0) { Element faultElement = (Element) faultNodes.item(0); faultElement.setPrefix(PREFERRED_PREFIX); } } }
package-info.java
包含 WSDL 生成类的包中的更改。我已经用我公司的命名空间前缀成功地做到了这一点,但它不适用于SOAP-ENV
前缀。@javax.xml.bind.annotation.XmlSchema(namespace = "http://www.example.com/ns/2008/02/02/webservices/blah", xmlns = { @javax.xml.bind.annotation.XmlNs(namespaceURI = "http://www.example.com/ns/2008/02/02/webservices/blah", prefix = ""), @javax.xml.bind.annotation.XmlNs(namespaceURI = "http://schemas.example.com/ns/2007/10/blah", prefix = "ns2"), @javax.xml.bind.annotation.XmlNs(namespaceURI = "http://example.com/ns/2007/23/05/blah/fundamental", prefix = "ns3"), @javax.xml.bind.annotation.XmlNs(namespaceURI = "http://schemas.xmlsoap.org/soap/envelope/", prefix = "soap") // doesn't work }, elementFormDefault = javax.xml.bind.annotation.XmlNsForm.QUALIFIED) package com.thomsonreuters.ts.ets.interdayws.soap.webservice;
Is there an ideal way to change SOAP-ENV
to soap
in Spring-WS?
有没有一种理想的方式来改变SOAP-ENV
,以soap
春,WS?
By the way, here's the code that set this prefix. StroapElement.java
顺便说一下,这是设置此前缀的代码。 StroapElement.java
采纳答案by attomos
A better solution
更好的解决方案
Use SOAPMessage APIinstead of DOM.
使用SOAPMessage API而不是 DOM。
private void alterSoapEnvelope(SaajSoapMessage soapResponse) {
try {
SOAPMessage soapMessage = soapResponse.getSaajMessage();
SOAPPart soapPart = soapMessage.getSOAPPart();
SOAPEnvelope envelope = soapPart.getEnvelope();
SOAPHeader header = soapMessage.getSOAPHeader();
SOAPBody body = soapMessage.getSOAPBody();
SOAPFault fault = body.getFault();
envelope.removeNamespaceDeclaration(envelope.getPrefix());
envelope.addNamespaceDeclaration(PREFERRED_PREFIX, SOAP_ENV_NAMESPACE);
envelope.setPrefix(PREFERRED_PREFIX);
header.setPrefix(PREFERRED_PREFIX);
body.setPrefix(PREFERRED_PREFIX);
if (fault != null) {
fault.setPrefix(PREFERRED_PREFIX);
}
} catch (SOAPException e) {
e.printStackTrace();
}
}
It's much faster now.
现在快多了。
回答by richard salazar
I use SAAJ. Try this.
我用 SAAJ。试试这个。
- soapEnvelope.removeNamespaceDeclaration("SOAP-ENV");
- soapEnvelope.addNamespaceDeclaration("soapenv", "http://schemas.xmlsoap.org/soap/envelope/");
- soapEnvelope.setPrefix("soapenv");
- soapHeader.setPrefix("soapenv");
- soapBody.setPrefix("soapenv");
- soapEnvelope.removeNamespaceDeclaration("SOAP-ENV");
- soapEnvelope.addNamespaceDeclaration("soapenv", " http://schemas.xmlsoap.org/soap/envelope/");
- soapEnvelope.setPrefix("soapenv");
- soapHeader.setPrefix("soapenv");
- soapBody.setPrefix("soapenv");
Don't forget: soapMessage.saveChanges();
不要忘记:soapMessage.saveChanges();
Reference:Changing the default XML namespace prefix generated with JAXWS