我最近惊讶地发现这个播放框架控制器动作代码中的 finally 块仅在异常之后被调用,但在调用实际成功时从未被调用。
try {
InputStream is = getInputStreamMethod();
renderBinary(is, "out.zip");
catch (Exception e) {
e.printStackTrace();
} finally {
cleanUp();
}
当调用 renderBinary() 时,线程可能被终止或发生了什么,但对我来说,这是不直观的。我怀疑其他 render() 调用也会发生同样的事情,但我没有验证它。
我通过将 renderBinary() 移到 try/catch 之后解决了这个问题。进一步的调查显示 play 提供了一个 @Finally 注释来创建一个在控制器操作执行后执行的方法。这里需要注意的是,这将在控制器中执行任何操作后被调用,因此它可能并不总是一个好的选择。
我的问题是:为什么 finally 块在 renderBinary() 之后没有被执行,这在任何地方都有记录吗?我在播放文档中找不到任何参考。
为了阐明导致这一发现的事件顺序:
由于 finally 块而应该被删除的文件没有被删除。
考虑到它不可能是由非执行 finally 块引起的,我更改了方法以使用 Amazon SQS 消息队列在 finally 块中发送消息——一个单独的作业接收消息并删除相关文件。
消息没有被发送。
我在代码中设置断点并确定正在调用 renderBinary,但 finally 块没有被执行。
为了安全起见,我在 finally 子句中添加了日志消息,但这些也不存在。
我重复了几次调试练习,每次都没有执行 finally 子句。
(请注意,实际代码并不像上面那样。这是一个非常简化的示例,只是为了说明情况。)