java - 如何更改 "SOAP-ENV"Spring-WS 的默认前缀

标签 java spring web-services soap spring-ws

我已经使用 Spring-WS 创建了一个 Web 服务。 为了保持与旧系统的兼容性,我需要将命名空间前缀从 SOAP-ENV 更改为 soap

我知道 SOAP-ENVsoap 只是 namespace 前缀。 只要它们引用正确的命名空间 ("http://schemas.xmlsoap.org/soap/envelope/"),就应该没问题。

但旧系统将解析器代码硬编码为仅期望 soap 命名空间前缀。

当前响应:

<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/">
   <SOAP-ENV:Header/>
   <SOAP-ENV:Body>
   ...
   </SOAP-ENV:Body>
</SOAP-ENV:Envelope>

预期响应:

<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
   <soap:Header/>
   <soap:Body>
   ...
   </soap:Body>
</soap:Envelope>

这是我到目前为止尝试过的方法

  1. 创建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);
        }
      }
    }
    
  2. 更改包含 WSDL 生成类的包中的 package-info.java。 我已经使用我公司的 namespace 前缀成功完成了此操作,但它不适用于 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;
    

在 Spring-WS 中,是否有一种理想的方法可以将 SOAP-ENV 更改为 soap

顺便说一句,这是设置这个前缀的代码。 StroapElement.java

最佳答案

更好的解决方案

使用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();
    }
  }

现在快多了。

关于java - 如何更改 "SOAP-ENV"Spring-WS 的默认前缀,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39242197/

相关文章:

java - WebDriverEventListener 中的 onException 何时触发?

java - 从网络存档执行命令

java - 将 Hibernate 5.2 与 Spring 框架 4.x 集成

jquery - 如何使用 Web 服务和 jQuery Ajax 启用 CORS

.net - 如何使用 Web 服务将在 .NET 中创建的 SQL 数据库连接到 Android

java - 我无法为我的应用程序创建抽屉导航 Activity

Java 类与 C++ 类

java - 我可以将 Socket.io 与 Spring-boot 一起使用吗?

Spring Cloud 配置服务器。属性中的环境变量

.net - 如何获取消息契约(Contract)以在正文而不是 header 中发送 SOAP 操作