java - 为什么 finally 在 playframework renderbinary 之后不阻止执行?

标签 java playframework try-catch-finally finally try-finally

我最近惊讶地发现,这个 play 框架 Controller 操作代码中的 finally block 只在异常之后被调用,但从未在调用真正成功时被调用。

try {
    InputStream is = getInputStreamMethod();
    renderBinary(is, "out.zip");
catch (Exception e) {
    e.printStackTrace();
} finally {
    cleanUp();
}

当调用 renderBinary() 时,可能线程终止或其他原因,但对我来说,这是不直观的。我怀疑其他 render() 调用也会发生同样的事情,但我没有验证。

我通过将 renderBinary() 移动到 try/catch 之后解决了这个问题。进一步的调查显示,play 提供了一个 @Finally 注释来创建一个在 Controller 操作执行后执行的方法。这里需要注意的是,这将在 Controller 中执行任何操作后被调用,因此它可能并不总是一个好的选择。

我的问题是:为什么 finally block 在 renderBinary() 之后没有执行,这在任何地方都有记录吗?我在 Play 文档中找不到任何引用。

阐明导致这一发现的事件顺序:

  1. 由于 finally block 而应该删除的文件没有被删除。

  2. 认为这不可能是由未执行的 finally block 引起的,我更改了使用 Amazon SQS Messaging Queue 在 finally block 中发送消息的方法——一个单独的作业接收消息并删除相关文件。

  3. 消息未发送。

  4. 我在代码中设置了断点并确定正在调用 renderBinary,但 finally block 没有被执行。

  5. 为了安全起见,我在 finally 子句中添加了日志消息,但这些消息也不存在。

  6. 我重复调试了几次,每次都没有执行 finally 子句。

(请注意,实际代码与上面的代码并不完全相同。这是一个非常简化的示例,只是为了说明情况。)

最佳答案

这是真的。我今天才知道这个,因为我的公司使用play框架,有人遇到了它。

据我了解,这可能只发生在 2.0 之前的 play 版本中,但是当您在渲染调用后捕获所有异常时,play 显然会将代码重写为跳过 finally block ...

我不明白这是为什么或具体是如何完成的,但显然是这样。

如果你捕捉到一个特定的异常,我认为这不会发生。

但是,是的,您既不是疯子也不是糟糕的程序员。这真的只是一个奇怪的、未记录的 play 问题。

关于java - 为什么 finally 在 playframework renderbinary 之后不阻止执行?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21313512/

相关文章:

java - 从 Play 2.4.1 迁移到 2.5.6 - 套接字

scala - 处理Scala : Future For Comprehension时出错

java - 对于未实现 AutoCloseable 的类,使用 lambda 是一种安全、正确且等效的解决方法吗?

java - 在try\finally block中有没有finally不执行的情况?

javascript - 无法到达 JavaScript 中的 catch block

java - JSP 不在 Spring 中显示模型中的对象

java - "Component model"是什么意思

java - 我是否正确使用了 Java swing 和图形?

Java 二维对象数组

scala - 从 Controller 中重构业务逻辑的好习惯方法