【问题标题】:Getting Raw XML From SOAPMessage in Java从 Java 中的 SOAPMessage 获取原始 XML
【发布时间】:2010-10-06 01:30:22
【问题描述】:

我已经在 J​​AX-WS 中设置了一个 SOAP WebServiceProvider,但是我无法弄清楚如何从 SOAPMessage(或任何节点)对象中获取原始 XML。这是我现在得到的代码示例,也是我试图获取 XML 的地方:

@WebServiceProvider(wsdlLocation="SoapService.wsdl")
@ServiceMode(value=Service.Mode.MESSAGE)
public class SoapProvider implements Provider<SOAPMessage>
{
    public SOAPMessage invoke(SOAPMessage msg)
    {
        // How do I get the raw XML here?
    }
}

有没有简单的方法来获取原始请求的 XML?如果有办法通过设置不同类型的 Provider(例如 Source)来获取原始 XML,我也愿意这样做。

【问题讨论】:

    标签: java soap jax-ws


    【解决方案1】:

    这是相当老的线程,但最近我遇到了类似的问题。我正在从一个休息服务调用一个下游soap服务,我需要按原样返回来自下游服务器的xml响应。

    所以,我最终添加了一个 SoapMessageContext 处理程序来获取 XML 响应。然后我将响应 xml 作为属性注入到 servlet 上下文中。

    public boolean handleMessage(SOAPMessageContext context) {
    
                // Get xml response
                try {
    
                    ServletContext servletContext =
                            ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest().getServletContext();
    
                    SOAPMessage msg = context.getMessage();
    
                    ByteArrayOutputStream out = new ByteArrayOutputStream();
                    msg.writeTo(out);
                    String strMsg = new String(out.toByteArray());
    
                    servletContext.setAttribute("responseXml", strMsg);
    
                    return true;
                } catch (Exception e) {
                    return false;
                }
            }
    

    然后我在服务层检索了xml响应字符串。

    ServletContext servletContext =
                    ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest().getServletContext();
    
            String msg = (String) servletContext.getAttribute("responseXml");
    

    还没有机会测试它,但这种方法必须是线程安全的,因为它使用的是 servlet 上下文。

    【讨论】:

      【解决方案2】:

      这行得通

       final StringWriter sw = new StringWriter();
      
      try {
          TransformerFactory.newInstance().newTransformer().transform(
              new DOMSource(soapResponse.getSOAPPart()),
              new StreamResult(sw));
      } catch (TransformerException e) {
          throw new RuntimeException(e);
      }
      System.out.println(sw.toString());
      return sw.toString();
      

      【讨论】:

      • 无需解释。
      【解决方案3】:

      使用变压器工厂:-

      public static String printSoapMessage(final SOAPMessage soapMessage) throws TransformerFactoryConfigurationError,
                  TransformerConfigurationException, SOAPException, TransformerException
          {
              final TransformerFactory transformerFactory = TransformerFactory.newInstance();
              final Transformer transformer = transformerFactory.newTransformer();
      
              // Format it
              transformer.setOutputProperty(OutputKeys.INDENT, "yes");
              transformer.setOutputProperty("{http://xml.apache.org/xslt}indent-amount", "2");
      
              final Source soapContent = soapMessage.getSOAPPart().getContent();
      
              final ByteArrayOutputStream streamOut = new ByteArrayOutputStream();
              final StreamResult result = new StreamResult(streamOut);
              transformer.transform(soapContent, result);
      
              return streamOut.toString();
          }
      

      【讨论】:

        【解决方案4】:

        如果您有客户端代码,则只需添加以下两行即可获取 XML 请求/响应。这里_callorg.apache.axis.client.Call

        String request = _call.getMessageContext().getRequestMessage().getSOAPPartAsString();
        String response = _call.getMessageContext().getResponseMessage().getSOAPPartAsString();
        

        【讨论】:

          【解决方案5】:

          仅出于调试目的,使用一行代码 -

          msg.writeTo(System.out);

          【讨论】:

          • OP 不一定要调试到 System.out(Web 服务器不一定可以方便地访问)——他/她可能需要通过套接字发送原始 XML,将其存储在某个地方,或计算其统计数据。
          • 您可以轻松地写信给ByteArrayOutputStream 转换为String...对我来说似乎很容易
          【解决方案6】:

          如果您有SOAPMessageSOAPMessageContext,您可以使用Transformer,通过DOMSource 将其转换为Source

                      final SOAPMessage message = messageContext.getMessage();
                      final StringWriter sw = new StringWriter();
          
                      try {
                          TransformerFactory.newInstance().newTransformer().transform(
                              new DOMSource(message.getSOAPPart()),
                              new StreamResult(sw));
                      } catch (TransformerException e) {
                          throw new RuntimeException(e);
                      }
          
                      // Now you have the XML as a String:
                      System.out.println(sw.toString());
          

          这将考虑到编码,因此您的“特殊字符”不会被破坏。

          【讨论】:

          • 提供的解决方案是不是很耗内存?
          【解决方案7】:

          你可以这样试试。

          SOAPMessage msg = messageContext.getMessage();
          ByteArrayOutputStream out = new ByteArrayOutputStream();
          msg.writeTo(out);
          String strMsg = new String(out.toByteArray());
          

          【讨论】:

          • 这里不考虑字符编码
          • 会不会因为构造 DOM 对象之类的东西而消耗大量内存?或者它真的会在没有内部解析 xml 的情况下从 HTTP 响应中给出原始字符串?
          【解决方案8】:

          事实证明,使用Provider可以得到原始的XML,方式如下:

          import java.io.ByteArrayOutputStream;
          import javax.xml.transform.Source;
          import javax.xml.transform.Transformer;
          import javax.xml.transform.TransformerFactory;
          import javax.xml.transform.stream.StreamResult;
          import javax.xml.ws.Provider;
          import javax.xml.ws.Service;
          import javax.xml.ws.ServiceMode;
          import javax.xml.ws.WebServiceProvider;
          
          @ServiceMode(value=Service.Mode.PAYLOAD)
          @WebServiceProvider()
          public class SoapProvider implements Provider<Source>
          {
              public Source invoke(Source msg)
              {
                  StreamResult sr = new StreamResult();
          
                  ByteArrayOutputStream out = new ByteArrayOutputStream();
                  sr.setOutputStream(out);
          
                  try {
                      Transformer trans = TransformerFactory.newInstance().newTransformer();
                      trans.transform(msg, sr);
          
                      // Use out to your heart's desire.
                  }
                  catch (TransformerException e) {
                      e.printStackTrace();
                  }    
          
                  return msg;
              }
          }
          

          我最终不需要这个解决方案,所以我自己并没有实际尝试过这个代码 - 它可能需要一些调整才能正确。但我知道这是从 Web 服务获取原始 XML 的正确途径。

          (如果您绝对必须有一个 SOAPMessage 对象,我不知道如何进行这项工作,但话又说回来,如果您要处理原始 XML,为什么要使用更高级别的对象? )

          【讨论】:

          • StringWriterByteArrayOutputStream+StreamResult 组合的一个很好的替代方案,如果您希望 XML 成为具有正确编码的 String
          【解决方案9】:

          如果您需要将 xml 字符串格式化为 xml,请尝试以下操作:

          String xmlStr = "your-xml-string";
          Source xmlInput = new StreamSource(new StringReader(xmlStr));
          Transformer transformer = TransformerFactory.newInstance().newTransformer();
          transformer.setOutputProperty(OutputKeys.INDENT, "yes");
          transformer.setOutputProperty("{http://xml.apache.org/xslt}indent-amount", "2");
          transformer.transform(xmlInput,
                  new StreamResult(new FileOutputStream("response.xml")));
          

          【讨论】:

          • 是否可以在空格和制表符之间进行选择来进行这种格式化?顺便说一句,我知道没有显示标签。
          猜你喜欢
          • 1970-01-01
          • 2012-11-03
          • 2011-04-29
          • 1970-01-01
          • 2021-11-02
          • 1970-01-01
          • 1970-01-01
          • 2011-06-08
          • 1970-01-01
          相关资源
          最近更新 更多