Jersey:HTTP 响应后关闭 I/O 资源

Jersey: Close I/O resources after HTTP response

我的设置: 我创建了一个 REST 服务 (Jersey/Dropwizard),它从数据库流式传输大量内容。在 GET 操作期间,服务通过连接池接入数据库,将数据包装到流中并执行一些即时转换以以各种编码(CSV、JSON、.. .).数据库连接的生命周期与流的生命周期相关,只有当流关闭时,数据库连接才会被释放。

流转换由编码器 class 执行,该编码器 return 是一个 StreamingOutput,然后传递给 Response 对象。当流被完全消耗时,编码器当前处理资源关闭。

我的问题:由于StreamingOutput没有实现AutoCloseable,当输出仅被部分消耗。

我有时会观察到过时的活动连接堆积在连接池中,我怀疑它们是由中止的 HTTP 连接引起的。如下所示,当前代码处理 try 块中发生的异常。我无法处理的是 return 语句之后发生的异常,我不知道如何将资源关闭的任何说明附加到 Response 对象。

我的问题: 我如何通知 Response 对象在请求终止后关闭特定资源(定期或由于错误)?或者:有没有更好的方法在请求上下文结束时安全地关闭任何关联的资源?

 @GET
 //@Produces(...)
 public Response streamData(
        @PathParam("key") String key,
        // ... other params
        ) {

    //decode and validate params
    Stream<Pojo> ps = null;
    try {
        // connect to db and obtain data stream for <key>
        ps = loadData(db, key);
        // apply detailed encoding instrunctions and create a StreamingOutput
        final StreamingOutput stream = Encoder.encodeData(ps, encodingArgs);
        return Response.ok(stream).build();
    } catch (Exception e) {
        closeOnException(ps); // wrapper for ps.close();
        throw e;
    }
 }

您可以将 HttpServletResponse 添加到您的方法中:

@Produces(MediaType.APPLICATION_OCTET_STREAM)
public Object streamData(
            @PathParam("key") String key,
            @Context HttpServletResponse response,
            // ... other params
            ) {
  ...
  response.getOutputStream().write(....)
  response.flushBuffer();
  response.getOutputStream().close();
  return null;
}

我从 dropwizard 邮件列表收到了一个很好的答案,它解决了我的问题,我想在这里引用它以防有人遇到同样的问题。

https://groups.google.com/forum/#!topic/dropwizard-user/62GoLDBrQuo

引用 Shawn 的回复:

Jersey 支持 CloseableService,允许您注册 Closeable 对象以在请求完成时关闭:

public Response streamData(..., @Context CloseableService closer) {
  ...
  closer.add(closeable);
  return Response.ok(...).build();
}