如何将OutputStream传递给StreamingDataHandler?

Dan*_*Lew 8 java jax-ws stream

我在JAX-WS中有一个Java Web服务,它从另一个方法返回一个OutputStream.我似乎无法弄清楚如何将OutputStream流式传输到返回的DataHandler,而不是创建一个临时文件,写入它,然后再将它作为InputStream重新打开.这是一个例子:

@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;
    }
}
Run Code Online (Sandbox Code Playgroud)

主要问题是writeToOut()方法可以返回远大于计算机内存的数据.这就是为什么该方法首先使用MTOM - 流式传输数据.我似乎无法解决如何直接从OutputStream流式传输数据,我需要提供给返回的DataHandler(最终是接收StreamingDataHandler的客户端).

我已经尝试过使用PipedInputStream和PipedOutputStream,但这些似乎并不是我需要的,因为在写入PipedOutputStream之后需要返回DataHandler.

有任何想法吗?

Dan*_*Lew 4

我按照 Christian 所说的思路找到了答案(创建一个新线程来执行 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;
    }
}
Run Code Online (Sandbox Code Playgroud)

由于变量的原因,它有点复杂final,但据我所知,这是正确的。当线程启动时,它会在第一次尝试调用时阻塞out.write();同时,输入流返回给客户端,客户端通过读取数据来解除写入阻塞。(我以前实现此解决方案的问题是我没有正确关闭流,因此遇到了错误。)