Java 如何通过Jersey响应对象同时传输OutputStream

Java 如何通过Jersey响应对象同时传输OutputStream,java,jersey,processbuilder,Java,Jersey,Processbuilder,我试图通过响应对象流式传输ProcessBuilder的输出。现在,只有在流程完成后,我才能在客户端获得输出。我希望看到客户端的输出同时被打印出来。目前,这是我的代码,它会在流程完成后在客户端(POSTMAN)打印出所有内容 StreamingOutput stream = new StreamingOutput() { @Override public void write(OutputStream os) throws IOException, WebApp

我试图通过响应对象流式传输ProcessBuilder的输出。现在,只有在流程完成后,我才能在客户端获得输出。我希望看到客户端的输出同时被打印出来。目前,这是我的代码,它会在流程完成后在客户端(POSTMAN)打印出所有内容

 StreamingOutput stream = new StreamingOutput() {
        @Override
        public void write(OutputStream os) throws IOException, WebApplicationException {
            String line;
            Writer writer = new BufferedWriter(new OutputStreamWriter(os));
            BufferedReader input = new BufferedReader(new InputStreamReader(process.getInputStream()));
            try {
                while ((line = input.readLine()) != null) {
                    writer.write("TEST");
                    writer.write(line);
                    writer.flush();
                    os.flush();;
                }
            } finally {
                os.close();
                writer.close();
            }            
        }
    };
    return Response.ok(stream).build();

您需要的是将输出缓冲区内容长度设置为0,以便jersey不缓冲任何内容。有关更多详细信息,请参见:

以下是Dropwizard独立应用程序,演示了以下内容:

public class ApplicationReddis extends io.dropwizard.Application<Configuration>{

    @Override
    public void initialize(Bootstrap<Configuration> bootstrap) {
        super.initialize(bootstrap);
    }

    @Override
    public void run(Configuration configuration, Environment environment) throws Exception {
        environment.jersey().property(ServerProperties.OUTBOUND_CONTENT_LENGTH_BUFFER, 0);
        environment.jersey().register(StreamResource.class);
    }

    public static void main(String[] args) throws Exception {
        new ApplicationReddis().run("server", "/home/artur/dev/repo/sandbox/src/main/resources/config/test.yaml");
    }

    @Path("test")
    public static class StreamResource{ 

        @GET
        public Response get() {
            return Response.ok(new StreamingOutput() {

                @Override
                public void write(OutputStream output) throws IOException, WebApplicationException {
                    for(int i = 0; i < 100; i++) {
                        output.write(("Hello " + i + "\n").getBytes());
                        output.flush();
                        try {
                            Thread.sleep(100);
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                    }
                }
            }).build();
        }
    }

}
此部分将出站长度设置为0。这将导致jersey不缓冲任何内容

您仍然需要刷新StreamingOutput中的outputstream,因为它有自己的缓冲区

用Dropwizard 1.0.2运行我上面的代码,每100毫秒会产生一行“hello”。使用curl,我可以看到所有输出都立即打印出来


您应该阅读文档以及设置
出站内容长度缓冲区的副作用,以确保不会引入不必要的副作用

了解一下这一点,了解客户机/请求者如何使用这些流数据。基本上,他将收到一条流作为响应。只是想知道如何处理这种情况。和往常一样,对客户端没有区别,只是它会更快地收到响应数据。所有的响应总是数据流。您的框架负责使它成为您可以使用的东西(即formdata、json正文、字符串等)。但是绝对没有什么可以阻止您访问响应流的原始数据并自己处理它。
environment.jersey().property(ServerProperties.OUTBOUND_CONTENT_LENGTH_BUFFER, 0);