jersey - StreamingOutput 作为响应实体

2022-01-21 00:00:00 java jersey jersey-client

我已经在我的 Jersey Resource 类中实现了流输出.

I had implemented streaming output in my Jersey Resource class.

@GET
@Path("xxxxx")
@Produces(BulkConstants.TEXT_XML_MEDIA_TYPE})   
public Response getFile() {

    FeedReturnStreamingOutput sout = new FeedReturnStreamingOutput();
    response = Response.ok(sout).build();
    return response;
}

class FeedReturnStreamingOutput implements StreamingOutput {

    public FeedReturnStreamingOutput()

    @Override
    public void write(OutputStream outputStream)  {
        //write into Output Stream
    }
}

问题是即使在调用 FeedReturnStreamingOutput 之前从资源发回响应,泽西客户端仍会等待直到 FeedReturnStreamingOutput 执行完成.

The problem is eventhough a response is sent back from the resource before FeedReturnStreamingOutput is called Jersey client waits until FeedReturnStreamingOutput execution is completed.

客户代码:

Client client = Client.create();

ClientResponse response = webResource
    //headers
    .get(ClientResponse.class);

//The codes underneath executes after FeedReturnStreamingOutput is executed which undermines the necessity of streaming

OutputStream os = new FileOutputStream("c:\test\feedoutput5.txt");
System.out.println(new Date() + " : Reached point A");

if (response.getStatus() == 200) {
    System.out.println(new Date() + " : Reached point B");
    InputStream io = response.getEntityInputStream();

    byte[] buff = new byte[1024000];
    int count = 0;

    while ((count = io.read(buff, 0, buff.length)) != -1) {
        os.write(buff, 0, count);
    }

    os.close();
    io.close();

} else {
    System.out.println("Response code :" + response.getStatus());
}

System.out.println("Time taken -->> "+(System.currentTimeMillis()-startTime)+" ms");

推荐答案

问题是 Jersey 用来缓冲实体以确定 Content-Length 标头的缓冲 OutputStream.缓冲区的大小默认为 8 kb.如果需要,您可以禁用缓冲,或者只是使用属性更改缓冲区的大小

The problem is the buffering OutputStream that Jersey uses to buffer the entity in order to determine the Content-Length header. The size of the buffer default to 8 kb. You disable the buffering if you want, or just change the size of the buffer, with the property

ServerProperties.OUTBOUND_CONTENT_LENGTH_BUFFER

一个整数值,定义用于缓冲服务器端响应实体的缓冲区大小,以确定其大小并设置 HTTPContent-Length"的值.标题.

An integer value that defines the buffer size used to buffer server-side response entity in order to determine its size and set the value of HTTP "Content-Length" header.

如果实体大小超过配置的缓冲区大小,缓冲将被取消,实体大小将无法确定.小于或等于零的值完全禁用实体的缓冲.

If the entity size exceeds the configured buffer size, the buffering would be cancelled and the entity size would not be determined. Value less or equal to zero disable the buffering of the entity at all.

此属性可用于在服务器端覆盖出站消息缓冲区大小值 - 默认值或使用jersey.config.contentLength.buffer"设置的全局自定义值.全局属性.

This property can be used on the server side to override the outbound message buffer size value - default or the global custom value set using the "jersey.config.contentLength.buffer" global property.

默认值为 8192.

这是一个例子

@Path("streaming")
public class StreamingResource {

    @GET
    @Produces("application/octet-stream")
    public Response getStream() {
        return Response.ok(new FeedReturnStreamingOutput()).build();
    }

    public static class FeedReturnStreamingOutput implements StreamingOutput {

        @Override
        public void write(OutputStream output)
                throws IOException, WebApplicationException {
            try {
                for (int i = 0; i < 10; i++) {
                    output.write(String.format("Hello %d
", i).getBytes());
                    output.flush();
                    TimeUnit.MILLISECONDS.sleep(500);
                }
            } catch (InterruptedException e) {  throw new RuntimeException(e); }
        }
    }
}

这是没有设置属性的结果

Here's the result without setting the property

这是将属性值设置为0

public class AppConfig extends ResourceConfig {
    public AppConfig() {
        ...
        property(ServerProperties.OUTBOUND_CONTENT_LENGTH_BUFFER, 0);
    }
}

相关文章