我想编写一个获取URI(可以是http,ftp,file,...)的Camel Route,然后获取数据并将其本地存储在文件中。
这个URI-String可以是,例如:
"FTP://localhost/example.txt"
"文件://tmp/example.txt"
"JMS:队列:dataInputQueue"
...
基于此字符串,应使用正确的Camel组件来访问数据。 像Java中的case / switch一样:
(1)接收URI(来自uri ="vm:incomingUri")
(2)选择"正确"的Camel组件
switch(URI)
case HTTP: use Camel HTTP component
case FTP: use Camel FTP component
case JMS: use Camel JMS component
...
(3)使用"正确的"Camel组件从该URI读取数据
(4)在本地存储文件(到uri ="file:// ...)
例:
从"vm:incomingUri"我读取一个字符串"ftp://localhost/example.txt"。 现在最终需要发生的事情应该等同于:
这在骆驼中看起来怎么样?
您最有可能想要查看新的"动态到"语法(如果您使用的是Camel 2.16+)或收件人列表模式。 两者都将允许动态评估uri。
我相信一个难点是,对于你提到的组件(HTTP,FTP,文件,JMS),你可能想要使用生产者或消费者:
FTP,文件:绝对是读取文件的消费者。
HTTP(或HTTP4):绝对是生产者,向服务器发送请求(服务器的回复将由新的消息体)
JMS:取决于您想要从队列(消费者)读取数据,还是使用ReplyTo标头将消息发送到队列,然后等待答案(生产者)。
制片人:
如果您使用的是Camel 2.16+,则可以使用新的"动态到"语法。它基本上与常规"to"相同,除了端点uri可以使用简单表达式(或者,optionnaly,另一种表达式)动态评估。或者,您可以使用内容丰富模式的enrich风格,也支持从Camel 2.16开始的动态uris。
如果您使用的是较旧版本的Camel,或者您需要动态路由到多个端点(而不仅仅是一个端点),则可以使用收件人列表模式。
这是一个例子。我们将通过调用端点来转换消息体;该端点的uri将在名为TargetUri的标头中找到,并将针对每条消息动态评估。
// An instance of this class is registered as 'testbean' in the registry. Instead of
// sending to this bean, I could send to a FTP or HTTP endpoint, or whatever.
public class TestBean {
public String toUpperCase(final String str) {
return str.toUpperCase();
}
}
// This route sends a message to our example route for testing purpose. Of course, we
// could send any message as long as the 'TargetUri' header contains a valid endpoint uri
from("file:inbox?move=done&moveFailed=failed")
.setHeader("TargetUri").constant("bean:testbean?method=toUpperCase")
.setBody().constant("foo")
.to("direct:test");
// 1. The toD example :
from("direct:test")
.toD("${header.TargetUri}")
.to("log:myRoute");
// 2. The recipient list example :
from("direct:test")
.recipientList(header("TargetUri"))
.to("log:myRoute");
// 3. The enrich example :
from("direct:test")
.enrich().simple("${header.TargetUri}") // add an AggregationStrategy if necessary
.to("log:myRoute");
消费者:
使用Camel 2.16+,您可以使用内容丰富模式的pollEnrich风格。
对于旧版本的Camel,您可以在处理器中使用ConsumerTemplate。
// 4. The pollEnrich example (assuming the TargetUri header contains, e.g., a file
// or ftp uri) :
from("direct:test")
.pollEnrich().simple("${header.TargetUri}") // add an AggregationStrategy if necessary
.to("log:myRoute");
// 5. The ConsumerTemplate example (same assumption as above)
from("direct:test")
.process(new Processor() {
@Override
public void process(Exchange exchange) throws Exception {
String uri = exchange.getIn().getHeader("TargetUri", String.class);
ConsumerTemplate consumer = exchange.getContext().createConsumerTemplate();
final Object data = consumer.receiveBody(uri);
exchange.getIn().setBody(data);
}
})
.to("log:myRoute");
制片人还是消费者?
可悲的是,我想不出任何真正优雅的解决方案来处理两者 - 我认为你必须根据uri和已知的组件路由到两个分支......这是我可能会做的事情(使用Camel 2.16+) ,它不是很漂亮:
// This example only handles http and ftp endpoints properly
from("direct:test")
.choice()
.when(header("TargetUri").startsWith("http"))
.enrich().simple("${header.TargetUri}")
.endChoice()
.when(header("TargetUri").startsWith("ftp"))
.pollEnrich().simple("${header.TargetUri}")
.endChoice()
.end()
.to("log:myRoute");
Re:"......或者如果你需要动态路由到多个端点"。我的问题是:我必须路由来自几个不同的端点(记住:我得到一个URI(作为String),并从该URI我必须得到数据。所以这个URI成为我的"来自("URI ..." ))。
我理解你的问题的方式是:你想从静态端点(vm:incomingUri)接收消息,然后路由到动态端点(取决于消息内容)来丰富/转换消息,然后最后发送富集/将消息转换为静态端点(file:...)。这就是我在我的例子中试图说明的内容。不是你想做什么的?您是否真的想设置新的路由,这些路由将继续从动态端点接收新消息?
更多地考虑一下:当你提到一个HTTP端点时,我的响应比你提到FTP或文件端点更有意义...使用HTTP(假设你发送了HTTP请求),你会想要使用一个生产者(和我一样)以java bean为例;使用FTP或文件,您将需要使用消费者...所以我认为您需要以不同于其他端点的方式调用某些端点(pollEnrich用于类似FTP; enrich,to或recipientList之类的东西像HTTP)。我试着把它添加到我的答案中。
"vm:incomingUri"只启动整个事情:从"vm:incomingUri"我只得到我需要读取的文件的URI(通过FTP或JMS或...)
我编辑的答案有帮助吗?
可以通过使用
但是你需要在属性中添加它。
并且您可以添加任何您想要http,ftp,file,log,jms,vm等的端点。
SomeEndPoint的价值。
日志组件:log:mock
JMS组件:activemq:someQueueName
文件组件:file:// someFileShare
VMComponent:vm:toSomeRoute
这对我来说不起作用,因为配置是静态的(请参阅原始问题中的编辑)