通过 Apache Camel 将 SQL 数据库中的二进制文件流式传输回端点

Streaming binary file from SQL Database through Apache Camel back to endpoint

当对我的 Camel 服务进行 REST 调用时,我试图从 SQL 数据库中获取一些 varbinary 数据。我可以将数据作为字节数组获取并将其设置为 Camel Exchange 的主体,然后 Servlet 将 return 作为原始字节发送给调用者(Web 浏览器、应用程序,随便)。

我现在正处于想要使用流而不是将所有字节保存在内存中的地步。如果我使用 JdbcTemplate,当 .query 方法完成时,我可以从结果集中获得的连接和流都将关闭,即使我尝试 return 一个 InputStream 和将其设置为 Exchange 正文。这阻止了我从数据库流式传输数据,直接通过 Camel,然后返回给调用者。

如果我自己写 jdbc 东西,我可以在打开时将流设置为交换体,但我认为我没有机会关闭我为此打开的连接和流,最终 运行 会因此耗尽资源。

我查看了 onCompletion,但我不知道如何使用它来关闭我没有参考的流和连接,我不确定在所有数据完成后是否一定会执行已流式传输回呼叫者。

我正在使用 Camel 2.14.1 中的 REST DSL 和 Servlet 组件。有没有什么方法可以在不写入文件的情况下完成此操作,稍后我会在某处使用定时任务清理该文件?我想避免这种情况,否则在哑计时器清理数据之前,您有一个竞争条件来流回数据。

事实证明,这样做的方法是,在查询数据库的 bean 中,从 ConnectionPool 中获取 Connection,创建 PreparedStatement 以获取任何列是您的数据,并执行它以使用 ResultSet.getBinaryStream.

请求您的二进制数据

这为您提供了一个 InputStream,您可以将其设置为您的 Camel Exchange body,如果您使用的是 REST DSL,则必须将 RestBindingMode.off 设置为您的 REST 端点。

将其设置为您的交换后 body,使用 setProperty("your_name_here", closeableresource).

将流、连接和结果集作为属性附加到您的交换中

请注意,将它们设置为 headers 可能会导致 Servlet 将它们绑定到响应中,此外通常会有一个最大 header 大小,这些将不适合.

bean 中的错误处理应该在错误情况下处理清理连接等。

然后在您的 REST 端点调用的路由上,有一个 onCompletion 子句,它只会在 REST 调用的使用者完成时执行。在该子句中,调用 Processor 提取您之前为需要关闭的资源设置的属性,对它们进行空检查,然后关闭它们。

抱歉缺少代码片段,希望我有时间回到这里,但以上内容应该足够了。

tl;dr:onCompletion 在所有流通过连接传回后执行,至少对于 Servlet 使用 Apache Camel .