Camel流程框架是Apache下的一個開源項目,是較爲成熟的流程框架。在web項目中也可以無縫地集成於Spring當中。
一、簡單使用
引入camel相關的jar包:camel-core-2.10.4.jar。
1、經典的入門示例——文件移動
public class FileMoveWithCamel {
public static void main(String[] args) {
try{
CamelContext camelCtx = new DefaultCamelContext();
camelCtx.addRoutes(new RouteBuilder() {
//此示例中,只能轉移文件,而無法轉移目錄
@Override
public void configure() throws Exception {
from("file:f:/tmp/inbox?delay=30000").to("file:f:/tmp/outbox");
}
});
camelCtx.start();
boolean loop = true;
while(loop) {
Thread.sleep(25000);
}
System.out.println("循環完畢");
camelCtx.stop();
} catch(Exception ex) {
ex.printStackTrace();
}
}
其中file:類似於http://,是camel的協議組件。camel支持的組件還包括:bean browse dataset direct file log mock properties seda test timer stub validator vm xlst等。其中常用的有bean和direct以及file
運行上述程序,會發現file:f:/tmp/inbox下的文件被轉移到file:f:/tmp/outbox了,並且在file:f:/tmp/inbox會生成一個.camel文件夾存放剛纔被轉移的文件。
2、入門示例二——帶Processor處理
先定義一個處理器,實現org.apache.camel.Processor接口
public class FileConvertProcessor implements Processor {
@Override
public void process(Exchange exchange) throws Exception {
// Object obj = exchange.getIn().getBody(); //如果是getBody()則返回一個Object
//如果是getBody(Class<T>)則返回T類型的實例
InputStream body = exchange.getIn().getBody(InputStream.class);
// System.out.println("進入:" + body);
BufferedReader br = new BufferedReader(new InputStreamReader(body, "UTF-8"));
StringBuilder sb = new StringBuilder("");
String str;
while((str = br.readLine()) != null) {
System.out.println(str);
sb.append(str + " ");
}
exchange.getOut().setHeader(Exchange.FILE_NAME, "converted.txt");
exchange.getOut().setBody(sb.toString());
System.out.println("body:" + exchange.getOut().getBody());
}
加上處理器後處理文件的程序
public class FileProcessWithCamel {
public static void main(String[] args) {
try{
CamelContext camelCtx = new DefaultCamelContext();
camelCtx.addRoutes(new RouteBuilder() {
@Override
public void configure() throws Exception {
FileConvertProcessor processor = new FileConvertProcessor();
//noop表示等待、無操作
from("file:f:/tmp/inbox?noop=true").process(processor).to("file:f:/tmp/outbox");
}
});
camelCtx.start();
boolean loop = true;
//死循環表示掛起camel上下文,以便持續監聽
while(loop) {
Thread.sleep(25000);
}
camelCtx.stop();
} catch(Exception ex) {
ex.printStackTrace();}
}
}
運行程序後將用一行打印file:f:/tmp/inbox下的文件的多行內容,並在file:f:/tmp/outbox下生成名爲converted.txt的文件。該文件的內容即爲file:f:/tmp/inbox下的文件的多行內容顯示成的一行。
這裏要特別注意getIn(setIn),getOut(setOut)怎麼用:先看下面一張圖
這張圖表明瞭:假設有流程A->B->C->D->……則A在處理完畢之後給B的話,A必須setOut結果,然後B要取流程中的“上一個”節點(即A)的結果則必須getIn取結果再處理,以此類推……A不能setIn結果,否則B getIn的話會取不到A set的結果。
二、集成在Spring當中
需引入camel-core-2.10.4.jar camel-spring-2.10.4.jar
對已第一部分的第一示例,若在Spring中配置,並設置它隨着web項目的啓動而啓動,則可以這樣寫:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:drools="http://drools.org/schema/drools-spring"
xmlns:camel="http://camel.apache.org/schema/spring"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd
http://drools.org/schema/drools-spring http://anonsvn.jboss.org/repos/labs/labs/jbossrules/trunk/drools-container/drools-spring/src/main/resources/org/drools/container/spring/drools-spring-1.0.0.xsd
http://camel.apache.org/schema/spring http://camel.apache.org/schema/spring/camel-spring.xsd">
<bean id="fileConverter" class="com.xxxx.FileConvertProcessor" />
<camelContext id="camel" autoStartup="true" xmlns="http://camel.apache.org/schema/spring">
<route>
<from uri="file:f:/tmp/inbox?delay=30000"/>
<process ref="fileConverter"/>
<to uri="file:f:/tmp/outbox"/>
</route>
</camelContext>
</beans>
除此之外,其實更爲常見的是一個處理流程往往需要經過很多個bean類。而查看camel direct組件的用法:
In the route below we use the direct component to link the two routes together:
可知bean與bean之間的流程連接用的是direct,這裏不妨用fileConverter和fileConverter2兩個Processor測試(它們的具體定義省略,都得實現Processor接口),於是:
<bean id="fileConverter" class="com.xxx.FileConvertProcessor" />
<bean id="fileConverter2" class="com.xxx.FileConvertProcessor2" />
<camelContext id="camel" autoStartup="true" xmlns="http://camel.apache.org/schema/spring">
<template id="producerTemplate" />
<threadPool id="pool" threadName="Thread-dataformat"
poolSize="50" maxPoolSize="200" maxQueueSize="250" rejectedPolicy="CallerRuns" />
<route>
<from uri="file:f:/tmp/inbox?delay=30000"/>
<process ref="fileConverter"/>
<to uri="file:f:/tmp/outbox"/>
<to uri="direct://start"/>
</route>
<route>
<from uri="direct://start"/>
<threads executorServiceRef="pool">
<process ref="fileConverter"/>
<to uri="bean://fileConverter2"/>
</threads>
</route>
</camelContext>
注意到上面第二個路由<route />中to的配置被放在一個線程池當中了,這也是比較常見的用法。這裏表明流程經過fileConverter處理,流向fileConverter2繼續處理。
另外,我們常常需要根據某一條件判斷流程的“下一步”應該走向哪裏,這時候就要用到類似el表達式的if else判斷了。再定義一個fileConverter3,表明根據條件選擇——流程在經過fileConverter時,根據配置條件選擇“下一步”流向fileConverter2還是fileConverter3(fileConverter2和fileConverter3定義省略,它們都得實現Processor接口)
<bean id="fileConverter" class="com.xxxx.FileConvertProcessor" />
<bean id="fileConverter2" class="com.xxx.FileConvertProcessor2" />
<bean id="fileConverter3" class="com.xxx.FileConvertProcessor3" />
<camelContext id="camel" autoStartup="true" xmlns="http://camel.apache.org/schema/spring">
<template id="producerTemplate" />
<threadPool id="pool" threadName="Thread-dataformat"
poolSize="50" maxPoolSize="200" maxQueueSize="250" rejectedPolicy="CallerRuns" />
<route>
<from uri="file:f:/tmp/inbox?delay=30000"/>
<process ref="fileConverter"/>
<to uri="file:f:/tmp/outbox"/>
<to uri="direct://start"/>
</route>
<route>
<from uri="direct://start"/>
<threads executorServiceRef="pool">
<choice>
<when>
<simple>${body.length} > 40</simple>
<process ref="fileConverter"/>
<to uri="bean://fileConverter2"/>
</when>
<otherwise>
<process ref="fileConverter"/>
<to uri="bean://fileConverter3"/>
</otherwise>
</choice>
</threads>
</route>
</camelContext>
<choice />和<otherwise />即表示選擇分支,而<when />下的<simple />標籤則用來放判斷條件,寫法和el表達式的條件判斷很類似。
注意Camel流程的開始時,應該在Java代碼中用ProducerTemplate.sendBody("direct://xxx",data)開始流程的源頭。ProducerTemplate是從配置文件的bean獲取(<template id="producerTemplate" />)的,然後ProducerTemplate.start()啓動Camel流程。然後在配置文件中通過<from uri="direct://xxx"/>開始接收流程傳過來的data數據。
---------------------
轉自 https://blog.csdn.net/qq_18875541/article/details/69391267