泽西岛:HTTP响应后关闭I / O资源

时间:2018-11-22 14:32:21

标签: java jersey response autocloseable

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

流转换由Encoder类执行,该类返回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;
    }
 }

2 个答案:

答案 0 :(得分:0)

您可以添加到方法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;
}

答案 1 :(得分:0)

我从dropwizard邮件列表中收到了很好的答案,可以解决我的问题,如果有人遇到相同的问题,我想在此引用。

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

引用肖恩的回应:

Jersey支持CloseableService,可让您注册在请求完成后要关闭的Closeable对象:

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