问题描述
我在JAX-WS中有一个Java Web服务,该服务从另一个方法返回OutputStream.除了创建临时文件,对其进行写入,然后再次将其作为InputStream备份打开之外,我似乎无法弄清楚如何将OutputStream流传输到返回的DataHandler中.这是一个示例:
I've got a Java web service in JAX-WS that returns an OutputStream from another method. I can't seem to figure out how to stream the OutputStream into the returned DataHandler any other way than to create a temporary file, write to it, then open it back up again as an InputStream. Here's an example:
@MTOM
@WebService
class Example {
@WebMethod
public @XmlMimeType("application/octet-stream") DataHandler service() {
// Create a temporary file to write to
File fTemp = File.createTempFile("my", "tmp");
OutputStream out = new FileOutputStream(fTemp);
// Method takes an output stream and writes to it
writeToOut(out);
out.close();
// Create a data source and data handler based on that temporary file
DataSource ds = new FileDataSource(fTemp);
DataHandler dh = new DataHandler(ds);
return dh;
}
}
主要问题是writeToOut()方法可以返回远大于计算机内存的数据.这就是为什么该方法首先使用MTOM来传输数据的原因.我似乎无法全神贯注于如何直接从需要提供给返回的DataHandler的OutputStream流数据(最终是接收StreamingDataHandler的客户端).
The main issue is that the writeToOut() method can return data that are far larger than the computer's memory. That's why the method is using MTOM in the first place - to stream the data. I can't seem to wrap my head around how to stream the data directly from the OutputStream that I need to provide to the returned DataHandler (and ultimately the client, who receives the StreamingDataHandler).
我已经尝试过使用PipedInputStream和PipedOutputStream,但这些似乎并不是我真正需要的,因为在将PipedOutputStream写入之后,需要返回DataHandler.
I've tried playing around with PipedInputStream and PipedOutputStream, but those don't seem to be quite what I need, because the DataHandler would need to be returned after the PipedOutputStream is written to.
有什么想法吗?
推荐答案
我按照Christian所说的思路(创建一个新线程执行writeToOut())找出了答案:
I figured out the answer, along the lines that Christian was talking about (creating a new thread to execute writeToOut()):
@MTOM
@WebService
class Example {
@WebMethod
public @XmlMimeType("application/octet-stream") DataHandler service() {
// Create piped output stream, wrap it in a final array so that the
// OutputStream doesn't need to be finalized before sending to new Thread.
PipedOutputStream out = new PipedOutputStream();
InputStream in = new PipedInputStream(out);
final Object[] args = { out };
// Create a new thread which writes to out.
new Thread(
new Runnable(){
public void run() {
writeToOut(args);
((OutputStream)args[0]).close();
}
}
).start();
// Return the InputStream to the client.
DataSource ds = new ByteArrayDataSource(in, "application/octet-stream");
DataHandler dh = new DataHandler(ds);
return dh;
}
}
由于final
变量,它有点复杂,但是据我所知这是正确的.当线程启动时,它在首次尝试调用out.write()
时会阻塞;同时,输入流返回给客户端,客户端通过读取数据来取消对写入的阻止. (我以前对该解决方案的实现存在的问题是我没有正确关闭流,从而遇到错误.)
It is a tad more complex due to final
variables, but as far as I can tell this is correct. When the thread is started, it blocks when it first tries to call out.write()
; at the same time, the input stream is returned to the client, who unblocks the write by reading the data. (The problem with my previous implementations of this solution was that I wasn't properly closing the stream, and thus running into errors.)
这篇关于如何将OutputStream管道传输到StreamingDataHandler?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!