【问题标题】:How to use a dynamic URI in From()如何在 From() 中使用动态 URI
【发布时间】:2015-11-28 21:28:29
【问题描述】:

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

(FTPHost, FTPUser, FTPPassword, FTPSourceDir, FTPDestDir)

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

示例: 这是我必须动态编写的骆驼路线示例

<Route>
    <from uri="ftp://${ftpUser}@${ftpHost}:${ftpPort}/${FTPSourceDir}?password=${ftpPassword}&delete=true"/>
    <to uri="${ftpDestinationDir}"/>
</Route>

正如您在示例中看到的,我需要动态传递这些提到的参数。 那么如何在From()中使用动态uri

【问题讨论】:

    标签: apache ftp apache-camel camel-ftp


    【解决方案1】:

    您可以从属性文件中读取它,如下所示,

    <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 中声明的直接组件

    注意:消费者和生产者模板的成本有点高。您可以将两者都注入弹簧容器并让弹簧处理生命周期。

    【讨论】:

    • 假设我有 3 个 ftp 服务器,如何将每个服务器一个接一个地传递到一个路由?
    【解决方案2】:

    从骆驼 2.16 开始,我们可以使用 pollenrich 组件来定义轮询消费者,如文件、ftp..etc,动态 url/参数值如下所示

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

    太棒了!!!

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

    【讨论】:

      【解决方案3】:

      我帮助一个运营消息代理的团队每天交换大约一百万条消息。我们必须从 50 多个目的地轮询所有文件共享品牌(FTP、SFTP、NFS/文件:...)的文件。与单个 FILE 连接器能够根据每个位置的特定时间表和安全设置轮询 50 个位置的文件相比,维护多达 50 个部署,每个部署每个都侦听不同的本地/远程目录确实是一种开销……获取相同的故事来自 pop3 和 IMAP 邮箱的电子邮件。

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

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

      而且效果很好。包含所有适用的错误处理和验证代码的确切实现代码有点过多,无法在此处发布,但您可以在上面找到相关“操作方法”的所有链接。

      【讨论】:

        【解决方案4】:

        我认为您可以在 Camel 路线中实现您的要求。

        因为您要轮询多个 FTP 站点,所以您必须以某种方式触发此过程。也许您可以基于Quartz2 计时器来执行此操作。一旦触发,您就可以读取配置的 FTP 站点from your database

        为了轮询给定的 FTP 站点,您可以使用 Content Enricher pattern 轮询(请参阅:pollEnrich)动态评估的 URI。

        您的最终基本路线可能如下所示(伪代码):

        from("quarz...")
        to("sql...")
        pollEnrich("ftp...")
        ...
        

        【讨论】:

          【解决方案5】:
          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>
          

          【讨论】:

            猜你喜欢
            • 2011-12-30
            • 1970-01-01
            • 2013-12-25
            • 2018-05-24
            • 1970-01-01
            • 2014-09-04
            • 2017-02-07
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多