我已經在Jetty之上使用Jersey2編寫了一個基本的REST服務器,用於測試HTTP Chunked Transfer-Encoding和gzip Content-Encoding。不過,我發現實現WriterInceptor以將GZIPOutputStream應用於gzip編碼的推薦方法會導致服務器阻塞,而不是通過gzip的塊發送。 我相信這是GZIPOutputStream等待它自己的緩衝區填滿,所以我試着在WriterInterceptor中重寫write()方法,以便在每次寫入後強制flush()(因爲我的服務器一次只寫一個塊),但是沒有區別。發生寫入時,是否有辦法強制刷新?java GZIPOutputStream塊ChunkedOutput http響應
App.java
public class App
{
public static int lineCount=0;
public static void main(String[] args) {
System.out.println("Hello World!");
ResourceConfig config = new ResourceConfig();
config.packages("com.example.mockAPIjava");
ServletHolder servlet = new ServletHolder(new ServletContainer(config));
EncodingFilter.enableFor(config, GZipEncoder.class);
Server server = new Server(2222);
ServletContextHandler context = new ServletContextHandler(server, "/*");
context.addServlet(servlet, "/*");
try {
server.start();
server.join();
} catch (Exception e) {
throw new RuntimeException(e);
} finally {
server.destroy();
}
}
}
GZIPWriterInterceptor.java
@Provider
@Compress
public class GZIPWriterInterceptor implements WriterInterceptor {
@Override
public void aroundWriteTo(WriterInterceptorContext context)
throws IOException, WebApplicationException {
MultivaluedMap<String,Object> headers = context.getHeaders();
headers.add("Content-Encoding", "gzip");
final OutputStream outputStream = context.getOutputStream();
context.setOutputStream(new GZIPOutputStream(outputStream) {
@Override
public void write(final int b) throws IOException {
out.write(b);
out.flush();
}
@Override
public void write(final byte[] b) throws IOException {
out.write(b);
out.flush();
}
@Override
public void write(final byte[] b, final int off, final int len) throws IOException {
out.write(b, off, len);
out.flush();
}
});
context.proceed();
}
}
Resource.java
@Path("stream")
public class Resource {
@GET
@Path("test")
@Compress
@Produces(MediaType.APPLICATION_JSON)
public ChunkedOutput<String> helloWorld(@Context HttpHeaders header, @Context HttpServletResponse response) {
final ChunkedOutput<String> output = new ChunkedOutput<String>(String.class, "\r\n");
new Thread() {
public void run() {
BufferedReader br = null;
try {
String chunk;
// open file for reading
File file = new File("/tmp/stream.txt");
FileReader fr = new FileReader(file);
br = new BufferedReader(fr);
while ((chunk = getNextString(br)) != null) {
// write a chunk every second
output.write(chunk);
try {
Thread.sleep(1 * 1000);
} catch(InterruptedException ex) {
Thread.currentThread().interrupt();
}
}
} catch (Exception e) {
// IOException thrown when writing the
// chunks of response: should be handled
e.printStackTrace();
} finally {
try {
output.close();
// simplified: IOException thrown from
// this close() should be handled here...
if (br!=null) { br.close(); }
} catch (IOException e1){
e1.printStackTrace();
}
}
}
}.start();
// the output will be probably returned even before
// a first chunk is written by the new thread
return output;
}
private String getNextString(BufferedReader br) throws IOException, ParseException {
App.lineCount++;
return br.readLine();;
}
}
Compress.java
//@Compress annotation is the name binding annotation for the GZIPWriterInterceptor
@NameBinding
@Retention(RetentionPolicy.RUNTIME)
public @interface Compress {}
Ahh..thanks。我更新了代碼,但行爲沒有改變。當我使用curl調用服務器時,我收到正確的響應頭,然後服務器掛起,直到它關閉流,而不是在寫入時立即發送每個塊。 <日期:孫老師,2017年2月26日22時04分54秒GMT <內容類型:應用程序/ JSON <有所不同:接受編碼 <內容編碼:gzip <傳輸編碼:分塊 <服務器:碼頭(9.2.3.v20140905) < – user3188040