如何使用Spring-WS直接传输SOAP?

我们希望在Web服务端点中启用有效负载的直接流式传输。 我们必须处理大量数据,并希望在处理时流式传输数据。

我们在版本2.0.0中使用spring-ws-core,并使用PayloadRootQNameEndpointMapping作为端点映射器。 作为消息工厂,我们使用的是AxiomSoapMessageFactory 。 我们实现StreamingPayload和相应的writeTo(XMLStreamWriter writer)方法,我们用它来编写有效负载(根据spring-ws JIRA票证, SWS-352 )。

这没有任何错误,但我们想直接流! 这显然是不可能的。 我们做了一个简单的测试,我们流式传输一些数据来评估行为。

 writer.writeStartElement("exampleResponse") 10000.times { writer.writeStartElement("example") writer.writeEndElement() } writer.writeEndElement() 

我们假设这将直接流式传输到使用者/客户端,因此soap头已经写入我们的编写器并在端点完成后关闭。 不幸的是,这是不可能的,流不能直接使用! 流被包装在Spring-ws源中的ByteArrayInputStream中。

StreamingOMDataSource的实现显示了这一点(可以在SpringEye中查看)。 StreamingOMDataSource调用您的StreamingPayload实现并为您提供一个编写器。

 public XMLStreamReader getReader() throws XMLStreamException { ByteArrayOutputStream bos = new ByteArrayOutputStream(); serialize(bos, null); ByteArrayInputStream bis = new ByteArrayInputStream(bos.toByteArray()); return StAXUtils.createXMLStreamReader(bis); } 

方法#serialize()使用ByteArrayOutputStream创建XMLStreamWriter ,并调用有效负载以启用写入,如上所述。

 public void serialize(OutputStream output, OMOutputFormat format) throws XMLStreamException { XMLStreamWriter streamWriter; if ([...]) { // Create stream writer with defined charset } else { streamWriter = StAXUtils.createXMLStreamWriter(output); } serialize(streamWriter); } public void serialize(XMLStreamWriter xmlWriter) throws XMLStreamException { payload.writeTo(xmlWriter); xmlWriter.flush(); } 

所以这对我来说无法使用。 是否有可能实现直接流媒体? 有什么想法吗? 先感谢您!


更新 :我最终为Spring WS创建了一个JIRA票证(SWS-704) 。 如果你想看到它实现,请考虑在JIRA页面上观看/投票。 希望我们至少得到一个有用的答复。

您还必须禁用有效负载缓存:

    

通过此设置,我们终于可以使用Spring WS执行SOAP的直接流式传输!

您不能(绝不应该)在Web服务中流式传输数据,就像在一个Web服务请求中通过HTTP连接不断地发送XML一样。 您必须进行许多单个Web服务调用,或将多个调用累积到一个中。

如果您需要高性能,Web服务并不是很好。 但是你可以手工优化简单的网络服务,这并不难。 但是,如果您需要更高的性能,切换到另一种传输格式将更多“钱”。 我仍然通过HTTP保存 – 特别是如果你有一些身份validation要求。

我只能想到这一点 – 堆栈(cxf,spring ws等)将缓冲整个消息,因为它们必须validation响应xml,以便能够在启用安全性时计算加密密钥等。

所以黑客就是编写你自己的自定义servlet / spring控制器,它将处理这个特定的响应并流出肥皂信封,然后是你的有效负载,然后是肥皂信封的结束标记。 这假设您没有任何WSS要求。