我正在使用 camel-cxfrs 组件来映射一个简单的 REST GET 操作,该操作返回从外部资源中提取的数据。一切正常,直到我决定启用“streamCache”,因为要返回的数据有时可能非常大(高达 50MB),我们不想将它加载到内存中,否则当执行多个请求时我们会耗尽内存同时!所以我配置了一个 DefaultStreamCachingStrategy 来定义何时将数据流式传输到 tmp 文件(例如大于 1MB 的数据)。
这工作正常,一旦从外部资源(DB 中的 blob !!)获取我的数据,它就会流回调用者,并且由于数据大于阈值,Camel 正在将我的输入流转换为 FileInputStreamCache,这很好......直到响应准备好通过 CXF 组件返回给调用者!因为消息传递给CXF组件,不再需要Camel交换(输出消息离开Camel上下文),所以创建的tmp文件在内容完全返回给REST之前被Camel删除(由它的TempFileManager实现)客户!!
这会导致 IOException,因为 CXF 组件试图从输入流(刚刚被 Camel 关闭)读取数据到 http 客户端。
知道如何解决这个问题吗?我需要保持 tmp 文件处于打开状态,直到所有响应数据都可以发送回 REST 客户端。但是一旦发送响应,就必须关闭并删除它。
这里我的骆驼上下文和一些豆子是如何定义的(没有显示一切):
<!-- ... -->
<cxf:rsServer address="/path" id="rsServer">
<cxf:providers>
<!-- ... -->
</cxf:providers>
<cxf:serviceBeans>
<ref bean="resourcesEndpoint"/>
</cxf:serviceBeans>
<!-- ... -->
</cxf:rsServer>
<!-- ... -->
<bean class="org.apache.camel.impl.DefaultStreamCachingStrategy" id="streamStrategy">
<property name="enabled" value="true"/>
<property name="bufferSize" value="512000"/>
<property name="spoolThreshold" value="512000"/>
<property name="spoolUsedHeapMemoryThreshold" value="8}"/>
<property name="spoolUsedHeapMemoryLimit" value="Max"/>
<property name="removeSpoolDirectoryWhenStopping" value="true"/>
<property name="anySpoolRules" value="true"/>
</bean>
<!-- ... -->
<camelContext id="context" streamCache="true" trace="false" useBreadcrumb="true" useMDCLogging="true" xmlns="http://camel.apache.org/schema/spring">
<!-- ... -->
<route id="mainRoute" >
<from id="fromCXFEndpoint" uri="cxfrs:bean:rsServer?bindingStyle=SimpleConsumer"/>
<recipientList id="_recipientList1">
<simple>direct:${header.operationName}</simple>
</recipientList>
</route>
<route id="downloadDataRoute" >
<from id="fromDownloadDataCXF" uri="direct:downloadData"/>
<!-- ... -->
<!-- Performing data fetching... not showing everything here! -->
<!-- ... -->
</route>
</camelContext>
接下来,用于映射 REST 请求的端点类:
@Path("/resources")
@Component
@Service
public class ResourcesEndpoint {
@GET
@Path("/data/{guid}")
@Produces({MediaType.TEXT_PLAIN, MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON, MediaType.APPLICATION_OCTET_STREAM})
public StreamingOutput downloadData(@PathParam("guid") String guid) {
return null;
}
}