通过 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 .
当对我的 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 .