5

正如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

4

5 回答 5

6

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

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

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

于 2015-09-03T07:51:58.463 回答
5

从骆驼 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

于 2015-09-24T17:47:47.237 回答
2

I help a team who operates a message broker switching about a million message per day. There are over 50 destinations from which we have to poll files over all file sharing brands (FTP, SFTP, NFS/file: ...). Maintaining up to 50 deployments that each listen to a different local/remote directory is indeed an overhead compared with a single FILE connector capable of polling files at the 50 places according to the specific schedule and security settings of each... Same story for getting e-mail from pop3 and IMAP mailboxes.

In Camel, the outline of a solution is as follows:

  • you have no choice but use the java DSL to configure at least the from() part of your routes with an URI that you can indeed read/build from a database or get from an admin request to initiate a new route. The XML DSL only allows injecting properties that are resolved once when the Camel context is built and never again afterwards.
  • the basic idea is to start routes, let them run (listen or poll a precise resource), and then shutdown & rebuild them on demand using the Camel context APIs to manage the state of RouteDefinitions, Routes, and possibly Endpoints
  • personally, I like to implement such dynamic from() instantiation on minimalist routes with just the 'from' part of the route, i.e. from(uri).to("direct:inboundQueue").routeId("myRoute"), and then define - in java or XML - a common route chunk that handles the rest of the process: from("direct:inboundQueue").process(..).etc... .to(outUri)
  • I'll advise strongly to combine Camel with the Spring framework, and in particular Spring MVC (or Spring Integration HttpGateway) so that you will enjoy the ability to quickly build REST, SOAP, HTTP/JSP, or JMX bean interfaces to administer route creation, destruction, and updates within a Spring + Camel container, both nicely integrated.
  • You can then declare in the Spring application context a bean that extends SpringRouteBuilder, as usual when building Camel routes with the java DSL in Spring; in the compulsory @Override configure() method implementation, you shall save your routeDefinition object built by the from(uri) method, and assign it a known String route-id with the .routeId(route-id) method; you may for instance use the route-id as a key in a Map of your route definition objects already created and started, as well as a key in your DB of URI's.
  • then you extend the SpringRouteBuilder bean you have declared with new methods createRoute(route-id), updateRoute(route-id), and removeRoute(route-id); The associated route-id parameters needed for create or update will be fetched from the database or another registry, and the relevant method, running within the RouteBuilder bean, will take advantage from the getContext() facility to retrieve the current ModelCamelContext, which in turn is used to stopRoute(route-id), removeRoute(route-id), and then addRouteDefinition(here is where you need the routeDefinition object), and finally startRoute(route-id) (Note: beware of possible ghost Endpoints that would not be removed, as explained in the removeRoute() javadoc)
  • your administrative interface (which typically takes the form of a Spring @Controller component/bean that handles the HTTP/REST/SOAP traffic) will indeed have an easy job to get the previously created SpringRouteBuilder extension Bean injected by Spring in the controller bean, and thus access all the necessary createRoute(route-id), updateRoute(route-id), and removeRoute(route-id) methods that you have added to the SpringRouteBuilder extension Bean.

And that works nicely. The exact implementation with all the error handling and validation code that applies is a bit too much code to be posted here, but you have all the links to relevant "how to's" in the above.

于 2015-09-18T15:02:37.723 回答
1

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

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

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

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

from("quarz...")
to("sql...")
pollEnrich("ftp...")
...
于 2015-09-05T11:36:04.783 回答
0
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>
于 2017-02-15T07:02:28.067 回答