我有一个运行在tomcat8上的servlet(使用Jersey)和一个用Java编写的客户端应用程序。要将从客户端应用程序导出的数据直接传输到Web服务器(而不是先导出所有数据然后再上传数据),我使用的是自定义InputStream实现。
一切正常,除了在这种情况下:
我正在从客户端开始数据传输,然后在数据仍在传输时关闭tomcat。日志消息显示请求已完成(我将unloadDelay设置为一个很高的值,以确保请求在关闭之前会完成),但是客户端在尝试读取响应时会抛出“ Premature EOF”异常。
我验证了流已完全传输到服务器。因此,在服务器处理InputStream之后,它将作为结果返回一个String,但是当尝试在客户端中读取结果时,服务器已经消失了。
如何才能正常关闭tomcat,这样仍在处理中的请求将完成而不会出现错误?
这是代码的一部分:
泽西资源的摘录
@POST
@Produces(MediaType.TEXT_PLAIN)
public Response handleData(InputStream data) {
String result = service.put(data);
log.info("handledData, result: " + result);
return Response.status(201).entity(result).build();
}
WebRequests.java中的代码段-使用jersey调用servlet的帮助程序类
private static Builder builder(String url, String sessionId, InputStream data) {
WebResource resource = createClient().resource(url);
Builder builder = resource.accept(MediaType.APPLICATION_JSON_TYPE, MediaType.TEXT_PLAIN_TYPE, MediaType.APPLICATION_OCTET_STREAM_TYPE);
builder.cookie(new Cookie("JSESSIONID", sessionId));
builder.entity(data, MediaType.APPLICATION_OCTET_STREAM_TYPE);
return builder;
}
private static Client createClient() {
ClientConfig config = new DefaultClientConfig();
config.getProperties().put(ClientConfig.PROPERTY_FOLLOW_REDIRECTS, false);
Client client = Client.create(config);
client.setChunkedEncodingSize(1024 * 100);
return client;
}
调用代码(CommitStream是自定义输入流):
InputStream stream = new CommitStream(db, message, data, callback);
String result = WebRequests.builder("http://....", sessionId, stream).post(String.class);
Stacktrace
java.io.IOException: Premature EOF
at sun.net.www.http.ChunkedInputStream.readAheadBlocking(ChunkedInputStream.java:565)
at sun.net.www.http.ChunkedInputStream.readAhead(ChunkedInputStream.java:609)
at sun.net.www.http.ChunkedInputStream.read(ChunkedInputStream.java:696)
at java.io.FilterInputStream.read(FilterInputStream.java:133)
at sun.net.www.protocol.http.HttpURLConnection$HttpInputStream.read(HttpURLConnection.java:3444)
at sun.nio.cs.StreamDecoder.readBytes(StreamDecoder.java:284)
at sun.nio.cs.StreamDecoder.implRead(StreamDecoder.java:326)
at sun.nio.cs.StreamDecoder.read(StreamDecoder.java:178)
at java.io.InputStreamReader.read(InputStreamReader.java:184)
at java.io.Reader.read(Reader.java:140)
at com.sun.jersey.core.util.ReaderWriter.readFromAsString(ReaderWriter.java:171)
at com.sun.jersey.core.util.ReaderWriter.readFromAsString(ReaderWriter.java:157)
at com.sun.jersey.core.provider.AbstractMessageReaderWriterProvider.readFromAsString(AbstractMessageReaderWriterProvider.java:114)
at com.sun.jersey.core.impl.provider.entity.StringProvider.readFrom(StringProvider.java:73)
at com.sun.jersey.core.impl.provider.entity.StringProvider.readFrom(StringProvider.java:58)
at com.sun.jersey.api.client.ClientResponse.getEntity(ClientResponse.java:634)