如何在From()中使用动态URI



正如Apache Camel中提到的,它允许在to()中写入动态URI,是否允许在From()中写入动态URI。因为我需要调用多个FTP位置来下载基于配置的文件,我要将其存储在数据库中。

(FTPHost, FTPUser, FTPPassword, FTPSourceDir, FTPDestDir)

我将从DB中读取这些配置,并在运行时动态地将其传递给Camel路由。

例子:这是骆驼路径的例子我需要动态地写

<Route>
    <from uri="ftp://${ftpUser}@${ftpHost}:${ftpPort}/${FTPSourceDir}?password=${ftpPassword}&delete=true"/>
    <to uri="${ftpDestinationDir}"/>
</Route>
如您在示例中看到的,我需要动态地传递上述参数。那么如何在From()

中使用动态uri呢?您可以从属性文件中读取它,如下所示:

<bean id="bridgePropertyPlaceholder" class="org.apache.camel.spring.spi.BridgePropertyPlaceholderConfigurer">
    <property name="location" value="classpath:/config/Test.properties"/>
  </bean> 
<Route>
    <from uri="ftp://{{ftpUser})@${{ftpHost}}:{{ftpPort}}/${{FTPSourceDir}}?password={{ftpPassword}}&delete=true"/>
    <to uri="{{ftpDestinationDir}}"/>
</Route>

ftpUser ftpHost…-所有的键都在Test.properties

中声明

如果你想动态地从你的交换器中获取这些变量,你不能像你在你的例子中提到的那样用常规的方式去做。你必须像下面这样使用消费者模板,

Exchange exchange = consumerTemplate.receive("ftp:"+url);
producerTemplate.send("direct:uploadFileFTP",exchange );

你必须从春豆或骆驼生产者那里做到这一点。消费者模板将从给定的组件中消费,并且该生产者模板将调用在camel-context.xml

中声明的直接组件。

注意:消费者和生产者模板有点昂贵。您可以将两者注入弹簧容器中,并让弹簧处理生命周期。

从camel 2.16开始,我们可以使用pollenrich组件定义轮询消费者,如file, ftp等,具有如下动态url/参数值

<route>
  <from uri="direct:start"/>
  <pollEnrich>
    <simple>file:inbox?fileName=${body.fileName}</simple>
  </pollEnrich>
  <to uri="direct:result"/>
</route>

awesomeeee ! !

参考:http://camel.apache.org/content-enricher.html

我帮助一个操作消息代理的团队每天交换大约一百万条消息。有超过50个目的地,我们必须从所有文件共享品牌(FTP, SFTP, NFS/file:…)中轮询文件。维护多达50个部署,每个部署监听一个不同的本地/远程目录,与能够根据每个地方的特定时间表和安全设置轮询50个地方的文件的单个FILE连接器相比,确实是一种开销。从pop3和IMAP邮箱接收电子邮件也是如此。

在Camel中,解决方案的大纲如下:

  • 你别无选择,只能使用java DSL配置至少from()部分的路由与一个URI,你确实可以从数据库读取/构建或从管理请求获得启动一个新的路由。XML DSL只允许注入在构建Camel上下文时解析一次的属性,以后再也不会解析。
  • 的基本思想是启动路由,让它们运行(监听或轮询一个精确的资源),然后关闭&使用Camel上下文 api按需重建它们,以管理RouteDefinitions、Routes和端点的状态
  • 就我个人而言,我喜欢在极简路由上实现这种动态的from()实例化,仅使用路由的'from'部分,即from(uri).to("direct:inboundQueue").routeId("myRoute"),然后定义-在java或XML中-处理其余进程的公共路由块:from("direct:inboundQueue").process(..).etc... .to(outUri)
  • 我强烈建议将CamelSpring框架结合起来,特别是Spring MVC(或Spring Integration HttpGateway),这样您就可以在Spring + Camel容器中快速构建REST、SOAP、HTTP/JSP或JMX bean接口来管理路由创建、销毁和更新,两者都很好地集成在一起。然后你可以在Spring应用程序上下文中声明一个扩展SpringRouteBuilder的bean,就像在Spring中使用java DSL构建Camel路由时一样;在强制@Override configure()方法实现中,您应该保存由from(uri)方法构建的routeDefinition对象,并使用.routeId(route-id)方法为其分配一个已知的String route-id;例如,你可以使用route-id作为已经创建和启动的路由定义对象的Map中的键,以及URI的DB中的键。
  • 然后你扩展SpringRouteBuilder bean,你已经声明了新的方法createRoute(route-id)updateRoute(route-id),和removeRoute(route-id);创建或更新所需的相关路由id参数将从数据库或另一个注册表中获取,并且在RouteBuilder bean中运行的相关方法将利用getContext()工具来检索当前的ModelCamelContext,它反过来用于stopRoute(route-id), removeRoute(route-id),然后addRouteDefinition( 这里是您需要routeDefinition对象 ),最后是startRoute(route-id)(注意:注意可能不会被删除的幽灵端点,正如removeRoute() javadoc)
  • 中所解释的那样
  • 您的管理接口(通常采用Spring @Controller组件/bean的形式,用于处理HTTP/REST/SOAP流量)确实可以轻松地将先前创建的SpringRouteBuilder扩展bean注入到控制器bean中,从而访问您添加到SpringRouteBuilder扩展bean中的所有必要的createRoute(route-id), updateRoute(route-id)removeRoute(route-id)方法。

效果很好。确切的实现与所有的错误处理和验证代码应用是有点太多的代码张贴在这里,但你有所有的链接到相关的"怎么做"在上面。

我认为您可以在Camel路由中实现您的需求。

因为您想轮询多个FTP站点,您必须以某种方式触发此过程。也许你可以基于Quartz2计时器来做这件事。一旦触发,您就可以从数据库中读取配置的FTP站点。

为了轮询给定的FTP站点,您可以使用Content enrichment模式轮询(参见:pollEnrich)一个动态评估的URI。

你最终的基本路由可能看起来像这样(伪代码):

from("quarz...")
to("sql...")
pollEnrich("ftp...")
...
Use Camel endpoint with spring spel expression.
Set up a Camel endpoint in the context so it can be accessed from any bean:
        <camelContext id="camel" xmlns="http://camel.apache.org/schema/spring">
            <endpoint id="inventoryQueue" uri="#{config.jms.inventoryQueueFromUri}"/>
        </camelContext>
Now you can reference the inventoryQueue endpoint within the `@Consume` annotation as follows:
        @org.apache.camel.Consume(ref = "inventoryQueue")
        public void updateInventory(Inventory inventory) {
            // update
        }
    Or:
    <route>
        <from ref="inventoryQueue"/>
        <to uri="jms:incomingOrders"/>
    </route>

最新更新