gpt4 book ai didi

java - 使用 JAX-WS 构建大型 MTOM/XOP 消息

转载 作者:塔克拉玛干 更新时间:2023-11-03 05:23:36 31 4
gpt4 key购买 nike

我对将 MTOM/XOP 与 JAX-WS 结合使用有疑问。我正在编写一个发送大量二进制数据的网络服务。客户端请求多个文件,服务器在响应中返回文件。

我能够让它正确构建响应,从而正确实现 XOP,但我遇到了与内存相关的问题,因为它在发送之前将整个 响应存储在内存中。此 Web 服务发送的文件可能非常大(例如,千兆字节大),因此无法将响应存储在内存中。

This Oracle website (以及 this one )似乎解决了这个问题,但我就是不明白。我认为他们使用 DataHandler 对象来流式传输请求/响应,但我不知道他们是如何实例化它的。

我正在使用 wsimport 从现有的 WSDL 生成我的 JAX-WS 类文件。我在 Java 6 中使用 JAX-WS RI 2.1.6。

如何在构建响应时发送响应,而不必先将所有内容存储在内存中?

预先感谢您的帮助。


12 月 17 日更新:我将以下属性添加到保存二进制数据的 WSDL 中的架构元素。这会导致 wsimportDataHandler 对象添加到 JAXB 类。然后可以将 FileDataHandler 添加到响应中,而不是添加文件的全部内容,从而允许服务器流式传输每个文件的内容,而不是将它们全部保存在内存中:

xmlns:xmime="http://www.w3.org/2005/05/xmlmime" 
xmime:expectedContentTypes="application/octet-stream"

因此,服务器现在正确构建响应,并且客户端在收到请求时将每个文件正确保存到磁盘。但是,出于某种原因,客户端仍然会将整个响应读入内存。


服务器代码(SIB):

@MTOM
@StreamingAttachment(parseEagerly = true, memoryThreshold = 4000000L)
@WebService(...)
public class DownloadFilesPortTypeImpl implements DownloadFilesPortType {
@Override
public FileSetResponseType downloadFileSet(FileSetRequestType body) {
FileSetResponseType response = new FileSetResponseType();
for (FileRequest freq : body.getFileRequest()){
try{
//find the file on disk
File file = findFile(freq.getFileId());

//read the file data into memory
byte[] fileData;
{
FileInputStream in = new FileInputStream(file);
ByteArrayOutputStream out = new ByteArrayOutputStream();
byte buf[] = new byte[8192];
int read;
while ((read = in.read(buf)) != -1){
out.write(buf, 0, read);
}
in.close();
out.close();
fileData = out.toByteArray();
}

//add the file to the response
FileResponse fresp = new FileResponse();
fresp.setFileId(freq.getFileId());
fresp.setData(fileData); //<-- type "xs:base64Binary"
response.getFileResponse().add(fresp);
}
catch (IOException e){
}
}

return response;
}
}

客户端代码:

DownloadFilesService service = new DownloadFilesService();
MTOMFeature mtomFeature = new MTOMFeature();
StreamingAttachmentFeature stf = new StreamingAttachmentFeature(null, true, 4000000L);
DownloadFilesPortType port = service.getDownloadFilesPortSoap12(mtomFeature, stf);

FileSetRequestType request = new FileSetRequestType();

FileRequest freq = new FileRequest();
freq.setFileId("1234");
request.getFileRequest().add(freq);

freq = new FileRequest();
freq.setFileId("9876");
request.getFileRequest().add(freq);

//...

FileSetResponseType response = port.downloadFileSet(request); //reads entire response into memory
for (FileResponse fres : response.getFileResponse()){
byte[] data = fres.getFileData();
//...
}

最佳答案

您创建自己的实现 DataSource 的类,并构造传入它的 DataHandler。它甚至可以是匿名的。

在 Apache CXF 中,我们可以更轻松地执行此操作。您可以只拥有一个返回 DataSource 或 DataHandler 的“getter”。您发布的代码中精心设计的方案对我来说并不熟悉。

我认为相同的方法适用于 JDK 的 JAX-WS+JAXB。参见 this .

关于java - 使用 JAX-WS 构建大型 MTOM/XOP 消息,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1916377/

31 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com