如何通过 Jersey 响应对象同时流式传输 OutputStream
How to simultaneously stream OutputStream via Jersey response object
我正在尝试通过响应对象流式传输 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,这样球衣就不会缓冲任何东西。有关更多详细信息,请参见:calling flush() on Jersey StreamingOutput has no effect
这是一个演示此操作的 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();
}
}
}
不要管 Dropwizard 部分,它只是在引擎盖下使用球衣。
environment.jersey().property(ServerProperties.OUTBOUND_CONTENT_LENGTH_BUFFER, 0);
这部分将出站长度设置为0。这将导致球衣不缓冲任何东西。
您仍然需要刷新 StreamingOutput 中的输出流,因为它有自己的缓冲区。
运行 我上面使用 Dropwizard 1.0.2 的代码将每 100 毫秒产生一行 "hello "。使用 curl 我可以看到所有输出都立即打印出来。
您应该阅读文档和设置 OUTBOUND_CONTENT_LENGTH_BUFFER
的副作用,以确保您没有引入不需要的副作用。
我正在尝试通过响应对象流式传输 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,这样球衣就不会缓冲任何东西。有关更多详细信息,请参见:calling flush() on Jersey StreamingOutput has no effect
这是一个演示此操作的 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();
}
}
}
不要管 Dropwizard 部分,它只是在引擎盖下使用球衣。
environment.jersey().property(ServerProperties.OUTBOUND_CONTENT_LENGTH_BUFFER, 0);
这部分将出站长度设置为0。这将导致球衣不缓冲任何东西。
您仍然需要刷新 StreamingOutput 中的输出流,因为它有自己的缓冲区。
运行 我上面使用 Dropwizard 1.0.2 的代码将每 100 毫秒产生一行 "hello "。使用 curl 我可以看到所有输出都立即打印出来。
您应该阅读文档和设置 OUTBOUND_CONTENT_LENGTH_BUFFER
的副作用,以确保您没有引入不需要的副作用。