【问题标题】:Catch exception streamingoutput捕获异常流输出
【发布时间】:2017-09-19 17:31:53
【问题描述】:

我看过很多关于如何使用StreamingOutput 的例子。就我而言,我想用它从数据库查询中流式传输 ResultSet。

ResultSet rs = (ResultSet) obj;
StreamingOutput stream = new StreamingOutput() {
    @Override
    public void write(OutputStream os) throws IOException,
                                       WebApplicationException {
        ResultSetFormatter.outputAsJSON(os, rs);

        res.close();
    }
};

return Response.ok(stream).build();

在这个意义上,write 方法定义包括一个throws IOException, WebApplicationException。我的问题出现在哪里。我需要正确关闭与数据库、结果集等的连接。如果在执行流式传输时抛出异常,我不知道如何捕获它。

我尝试了以下代码,但它不是有效代码,因为 IOException 不是从 try-catch 块中抛出的。

try {
    ....  launch request to database ...
    ResultSet rs = (ResultSet) obj;
    StreamingOutput stream = new StreamingOutput() {
        @Override
        public void write(OutputStream os) throws IOException,
                                           WebApplicationException {
            if (accept.equals("application/json") {
                ResultSetFormatter.outputAsJSON(os, rs);
            } else {
                ResultSetFormatter.outputAsXML(os, rs);
            }

            res.close();
        }
    };

    return Response.ok(stream).build();
} catch (IOException | WebApplicationException e) {
    // Do cleanup
}

我该如何继续?是否可以正确清理所有内容?我什至认为在 write 方法中包含所有数据处理,但问题是,如果不修复,我无法设置响应的内容类型。

TIA

编辑 1:我使用的是基于 Jena 而不是 SQL 数据库的 SPARQL 语句。根据查询的类型,我得到不同类型的响应(模型、结果集或布尔值)。然后每个都有不同的有效内容类型,所以在执行或分析查询之前我无法设置响应的内容类型。

【问题讨论】:

  • 你想在这里完成什么?这段代码在什么地方运行?看起来您正在尝试复制延迟加载的数据。可能有更好的方法来实现这一点。
  • 我有一个很大的结果集,否则我必须在本地存储在内存中。我想将它直接流式传输到客户端。如果发生某些事情,就会出现问题,因为我必须关闭结果集等以释放资源。我不明白你懒惰的数据加载。
  • 查看 thread 了解延迟加载
  • 我不认为是延迟加载。正如我告诉过你的,我不想将整个结果集存储在内存中来创建字符串。我更喜欢直接流式传输。
  • 您似乎希望在使用数据时加载数据,而不是加载所有内容然后将数据传递给您的 Web 服务的响应,即延迟加载。在任何情况下,除了语义,通常您希望您的服务根据每个请求处理数据库事务。这将使您的结果保持活力,直到它们被消耗掉。如果不知道您是否正在使用任何框架,或者这是一个 servlet 还是其他东西,就很难进入细节。

标签: java http outputstream resource-cleanup


【解决方案1】:

您可以查看try-with-resources,它会自动为您关闭它。

在 Java SE 7 之前,要走的路是通过 finally。无论try 退出点如何,它都会执行。

【讨论】:

  • 我有那个try-with-resources,但问题是resulset然后关闭,因为流是在返回后执行的东西,然后当StreamingOutput write被调用时它抱怨结果集不再有效。所以这对我无效:(
【解决方案2】:

user8 是对的,但没有提供详细信息。您希望在 write 方法中使用 try-with-resources 语句:

@Override
public void write(OutputStream os) throws IOException,
                                   WebApplicationException {

    try (Statement statement = rs.getStatement();
         Connection conn = statement.getConnection()) {

        if (accept.equals("application/json") {
            ResultSetFormatter.outputAsJSON(os, rs);
        } else {
            ResultSetFormatter.outputAsXML(os, rs);
        }
    }
}

自动关闭语句也会automatically close the ResultSet

【讨论】:

  • 没错,但问题是accept的值是根据查询的响应类型来检索的。我使用的是 Sparql 而不是 SQL,我可以获得不同类型的响应(模型、结果集或布尔值)。我已经更新了我的问题。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2023-03-26
  • 2013-06-24
  • 1970-01-01
  • 2014-09-11
  • 2016-02-17
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多