【问题标题】:Remove/Modify XML declaration of a SOAP response message删除/修改 SOAP 响应消息的 XML 声明
【发布时间】:2015-04-22 21:44:52
【问题描述】:

通过 HTTP POST 请求调用 JAX-WS Webservice 的操作,我们通常会得到如下示例格式的响应:

<?xml version="1.0" encoding="UTF-8" ?>
<S:Envelope xmlns:S="http://schemas.xmlsoap.org/soap/envelope/">
 <S:Body>
    <ns2:helloResponse xmlns:ns2="http://test/">
       <return>Hello Foo!</return>
    </ns2:helloResponse>
 </S:Body>
</S:Envelope> 

我想删除和/或修改 服务器端的 SOAP 消息响应的 XML 声明的版本,即我想从我的 WS 的响应中删除/修改这部分:

<?xml version="1.0" encoding="UTF-8" ?>

我尝试使用 JAX-WS SOAPMessage 处理程序(请参阅下面的代码)将其删除,但它不起作用。

@Override
public boolean handleMessage(SOAPMessageContext context) {
    Boolean isRequest = (Boolean) context.get(MessageContext.MESSAGE_OUTBOUND_PROPERTY);
    if(isRequest) {
        try {
            final SOAPMessage message = context.getMessage();
            message.setProperty(SOAPMessage.WRITE_XML_DECLARATION, "false");
            message.saveChanges();
            context.setMessage(message);
        } catch (SOAPException e) {
            return false;
        }
    }
    return true;
}

我做错了什么?这甚至可能吗???如果是,您对如何删除 XML 声明或修改它的版本(到 XML 1.1)有什么建议吗??

非常感谢您的帮助!

【问题讨论】:

  • 等待..您在服务器或客户端处理/期望? (请尝试if(!isRequest)!)
  • @xerx593 对不起,忘了说我在服务器端处理消息
  • 所以“你做错了什么?”仍然是最难的问题,“有可能吗?” - 我同意,你的方法朝着正确的方向发展! “xml 1.1” - 我不推荐,因为这个 xml 版本不存在(但..也许永远存在)
  • 我遇到了同样的问题。在我的情况下,服务器(我无法更改)不接受具有 XML 声明的 SOAP 请求。

标签: java soap jax-ws


【解决方案1】:

在 JAX-WS 服务的响应中删除 XML 声明(这应该不需要,但我们都遇到了一个发誓它破坏他们的系统的集成方,对吗?) ,很难找到一种万能的解决方案。在我调试的实现中,大多数假设您想要声明,并无条件地添加它。

我能想到的最安全的方法是将这个困境排除在 JAX-WS 范围之外。相反,可以使用 servlet 过滤器来修改由 JAX-WS 实现生成的 servlet 响应。

这段代码(与 Servlet 3.0 兼容)创建了一个简单的过滤器,它使用 ServletResponseWrapper 来修改响应,就在它被发送回客户端之前。为了更好地衡量,它只对“text/xml”内容进行操作。

import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpServletResponseWrapper;
import java.io.*;

/**
 * A servlet filter that allows one to strip the XML declaration from xml-based
 * responses.
 *
 * @author Guus der Kinderen.
 */
@WebFilter( "/*" )
public class XmlDeclarationFilter implements Filter
{
    public void doFilter( ServletRequest request,
                          ServletResponse response,
                          FilterChain chain )
                          throws ServletException, IOException
    {
        try ( final Writer out = response.getWriter() )
        {
            // Will hold original response.
            final Wrapper wrapper = new Wrapper((HttpServletResponse) response );

            // Proceed with the request (will populate wrapper).
            chain.doFilter( request, wrapper );

            // Process the populated wrapper.
            if ( wrapper.getContentType().contains( "text/xml" ) )
            {
                // Modify the original content (strip the XML declaration).
                final String regex = "(?s)^\\s*\\<\\?xml.*?>";
                final String original = wrapper.toString();
                final String modified = original.replaceFirst( regex, "" );

                // Adjust the content length value to account for any changes.
                response.setContentLength( modified.length() );

                // Send out the modified content as a response.
                out.write( modified );
            }
            else
            {
                // Send out the original content, unmodified.
                out.write( wrapper.toString() );
            }
        }
    }

    /**
     * A response wrapper that buffers all output, and makes it available as 
     * a String.
     *
     * @author Guus der Kinderen.
     */
    public class Wrapper extends HttpServletResponseWrapper
    {
        final ByteArrayOutputStream baos = new ByteArrayOutputStream();

        public Wrapper( HttpServletResponse response )
        {
            super( response );
        }

        public String toString()
        {
            try
            {
                return baos.toString( "utf-8" );
            }
            catch ( UnsupportedEncodingException e )
            {
                return baos.toString();
            }
        }

        @Override
        public PrintWriter getWriter()
        {
            return new PrintWriter( baos );
        }

        @Override
        public ServletOutputStream getOutputStream() throws IOException
        {
            return new ServletOutputStream()
            {
                @Override
                public void write( int b ) throws IOException
                {
                    baos.write( b );
                }
            };
        }
    }

    public void init( FilterConfig config ) throws ServletException
    {
    }

    public void destroy()
    {
    }
}

【讨论】:

    【解决方案2】:

    你真的需要删除 xml 声明吗?

    我有一种情况,如果我发送没有 xml 声明的肥皂消息,它会起作用。 如果我发送带有 xml 声明的 soap 消息,将返回此错误:

    org.xml.sax.SAXParseException: The XML declaration must end with "?>"
    

    我也尝试设置 WRITE_XML_DECLARATION,但没有成功。

    我的解决方案是设置这两个 NamespaceDeclaration:

    SOAPEnvelope env = sp.getEnvelope();
    env.addNamespaceDeclaration("xsd", "http://www.w3.org/2001/XMLSchema");
    env.addNamespaceDeclaration("xsi", "http://www.w3.org/2001/XMLSchema-instance");
    

    完整的解决方案描述请参考Removing XML declaration in JAX-WS message

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-12-05
      • 1970-01-01
      • 2012-09-10
      • 2014-10-19
      • 1970-01-01
      相关资源
      最近更新 更多