Apache Camel的Java編程入門指南
Apache Camel是一個(gè)非常實(shí)用的規(guī)則引擎庫,能夠用來處理來自于不同源的事件和信息。你可以在使用不同的協(xié)議比如VM,HTTP,F(xiàn)TP,JMS甚至是文件系統(tǒng)中來傳遞消息,并且讓你的操作邏輯和傳遞邏輯保持分離,這能夠讓你更專注于消息的內(nèi)容。
在這篇文章中,我將提供一個(gè)Java語言(非Groovy)的Apache Camel入門演示。
首先創(chuàng)建一個(gè)Maven項(xiàng)目的pom.xml。
<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation=" http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>camel-spring-demo</groupId> <artifactId>camel-spring-demo</artifactId> <version>1.0-SNAPSHOT</version> <packaging>jar</packaging> <properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <camel.version>2.11.1</camel.version> </properties> <dependencies> <dependency> <groupId>org.apache.camel</groupId> <artifactId>camel-core</artifactId> <version>${camel.version}</version> </dependency> <dependency> <groupId>org.slf4j</groupId> <artifactId>slf4j-simple</artifactId> <version>1.7.5</version> </dependency> </dependencies> </project>
在這里我們只用到了camel-core.jar包,實(shí)際上它提供了許多你可能用到的實(shí)用組件。出于日志記錄的目的,我使用了slf4j-simple來作為日志記錄的實(shí)現(xiàn),從而我們可以從控制臺上看到輸出。
接下來我們只需要構(gòu)造一個(gè)路由類。路由就好比是Camel中怎樣將消息從一端傳遞到另一端的一個(gè)指令定義。我們將會創(chuàng)建src/main/java/camelcoredemo/TimerRouteBuilder.java文件,每隔一秒向處理器發(fā)送一個(gè)消息,簡單打印出來。
package camelcoredemo; import org.slf4j.*; import org.apache.camel.*; import org.apache.camel.builder.*; public class TimerRouteBuilder extends RouteBuilder { static Logger LOG = LoggerFactory.getLogger(TimerRouteBuilder.class); public void configure() { from("timer://timer1?period=1000") .process(new Processor() { public void process(Exchange msg) { LOG.info("Processing {}", msg); } }); } }
以上就是這個(gè)示例的全部所需,現(xiàn)在編譯運(yùn)行。
bash> mvn compile bash> mvn exec:java -Dexec.mainClass=org.apache.camel.main.Main -Dexec.args='-r camelcoredemo.TimerRouteBuilder'
注意,這里我們并沒有編寫Java類的main入口,我們只是將RouteBuilder的類名當(dāng)作參數(shù)簡單傳遞給 org.apache.camel.main.Main,然后它將自動加載路由。
控制CamelContext
當(dāng)啟動Camel后,它會創(chuàng)建一個(gè)CamelContext對象,該對象擁有了很多關(guān)于如何運(yùn)行Camel的信息,還包含我們所創(chuàng)建的Route的定義?,F(xiàn)在如果你想通過CamelContext獲得更多的控制,那么你需要編寫自己的主類代碼。我在這舉個(gè)簡單的例子。
package camelcoredemo; import org.slf4j.*; import org.apache.camel.*; import org.apache.camel.impl.*; import org.apache.camel.builder.*; public class TimerMain { static Logger LOG = LoggerFactory.getLogger(TimerMain.class); public static void main(String[] args) throws Exception { new TimerMain().run(); } void run() throws Exception { final CamelContext camelContext = new DefaultCamelContext(); camelContext.addRoutes(createRouteBuilder()); camelContext.setTracing(true); camelContext.start(); Runtime.getRuntime().addShutdownHook(new Thread() { public void run() { try { camelContext.stop(); } catch (Exception e) { throw new RuntimeException(e); } } }); waitForStop(); } RouteBuilder createRouteBuilder() { return new TimerRouteBuilder(); } void waitForStop() { while (true) { try { Thread.sleep(Long.MAX_VALUE); } catch (InterruptedException e) { break; } } } }
可以看到,我們在createRouteBuilder()方法中重用了已有的TimerRouteBuilder類。現(xiàn)在我們的主類對在什么時(shí)候創(chuàng)建、啟動、停止CamelContext有了完全的控制。context(camelContext)對象允許你全局性地控制如何配置Camel,而不是在Route級。它的JavaDoc鏈接給出了所有setter方法,你可以研究下它都可以做些什么。
注意到一點(diǎn),我們也需要在我們的主類中提供少量設(shè)置代碼。首先我們需要處理優(yōu)雅關(guān)閉的問題,所以我們增加了一個(gè)Java關(guān)閉回調(diào)函數(shù)去調(diào)用context的stop()方法。其次在context已經(jīng)啟動后,我們需要增加一個(gè)線程阻塞。如果在啟動后你不阻塞你的主線程,那么它會在啟動后就簡單的退出了,那就沒啥用了。你會把Camel一直作為一個(gè)服務(wù)(就像一個(gè)服務(wù)器)運(yùn)行,直至你按下CTRL+C鍵去終止該進(jìn)程。
改善啟動CamelContext的主類
如果你不想像上面例子一樣過多的處理主類設(shè)置代碼,那么你可以簡單地繼承由camel-core提供的org.apache.camel.main.Main類作為代替。通過利用這個(gè)類,你不僅可以讓你的context自動設(shè)置,還可以獲得所有附加的命令行特性,比如控制進(jìn)程運(yùn)行多久,啟用追蹤,加載自定義route類等等。
重構(gòu)了下上一個(gè)例子,代碼如下:
package camelcoredemo; import org.slf4j.*; import org.apache.camel.builder.*; import org.apache.camel.main.Main; public class TimerMain2 extends Main { static Logger LOG = LoggerFactory.getLogger(TimerMain2.class); public static void main(String[] args) throws Exception { TimerMain2 main = new TimerMain2(); main.enableHangupSupport(); main.addRouteBuilder(createRouteBuilder()); main.run(args); } static RouteBuilder createRouteBuilder() { return new TimerRouteBuilder(); } }
現(xiàn)在TimerMain2類的代碼比之前的更少了,你可以試試看,它應(yīng)該和之前的功能一樣。
bash> mvn compile bash> mvn exec:java -Dexec.mainClass=camelcoredemo.TimerMain2 -Dexec.args='-t'
注意到我們給出-t選項(xiàng)后,會轉(zhuǎn)儲Route追蹤。使用-h會看到所有可用的選項(xiàng)。
用Camel的注冊機(jī)制添加bean
在之前的TimerRouteBuilder例子中,我們已經(jīng)在代碼中創(chuàng)建了一個(gè)匿名Processor?,F(xiàn)在如果你想將幾個(gè)不同的Processor放在一起,那么使用Camel的注冊機(jī)制添加bean的方式將能更好的減少代碼混亂。Camel允許你通過將processing當(dāng)作bean注入到它的registry space,然后你只要把它們當(dāng)作bean組件來進(jìn)行調(diào)用。如下是我的重構(gòu)代碼:
package camelcoredemo; import org.slf4j.*; import org.apache.camel.*; import org.apache.camel.builder.*; import org.apache.camel.main.Main; public class TimerBeansMain extends Main { static Logger LOG = LoggerFactory.getLogger(TimerBeansMain.class); public static void main(String[] args) throws Exception { TimerBeansMain main = new TimerBeansMain(); main.enableHangupSupport(); main.bind("processByBean1", new Bean1()); main.bind("processAgainByBean2", new Bean2()); main.addRouteBuilder(createRouteBuilder()); main.run(args); } static RouteBuilder createRouteBuilder() { return new RouteBuilder() { public void configure() { from("timer://timer1?period=1000") .to("bean:processByBean1") .to("bean:processAgainByBean2"); } }; } // Processor beans static class Bean1 implements Processor { public void process(Exchange msg) { LOG.info("First process {}", msg); } } static class Bean2 implements Processor { public void process(Exchange msg) { LOG.info("Second process {}", msg); } } }
現(xiàn)在Route類更簡潔明了,同時(shí)處理代碼也被重構(gòu)到了獨(dú)立的類中。當(dāng)你需要編寫很復(fù)雜的Route來實(shí)現(xiàn)業(yè)務(wù)邏輯時(shí),這種方式能夠幫助你更好的組織和測試你的代碼。它能夠讓你構(gòu)建像”樂高“積木那樣可復(fù)用的POJO bean。Camel的registry space同樣可用于其他很多用途,比如你可以自定義許多具有附加功能的endpoint組件或者注冊一些信息,更或者替換線程池實(shí)現(xiàn)策略之內(nèi)的事情。
上述Route示例是用所謂的Java DSL來構(gòu)成的,它的可讀性較高,你可以用IDE提供的支持查看所有可用于Route的方法。
我希望這篇文章能夠幫助你跳過Camel的摸索階段。
上一篇:舉例講解設(shè)計(jì)模式中的訪問者模式在Java編程中的運(yùn)用
欄 目:Java編程
下一篇:詳解Java編程中Annotation注解對象的使用方法
本文標(biāo)題:Apache Camel的Java編程入門指南
本文地址:http://mengdiqiu.com.cn/a1/Javabiancheng/8475.html
您可能感興趣的文章
- 01-10JVM的垃圾回收機(jī)制詳解和調(diào)優(yōu)
- 01-10Java進(jìn)階:Struts多模塊的技巧
- 01-10J2SE 1.5版本的新特性一覽
- 01-10Java Socket編程(二) Java面向連接的類
- 01-10Java運(yùn)行時(shí)多態(tài)性的實(shí)現(xiàn)
- 01-10Java經(jīng)驗(yàn)點(diǎn)滴:處理沒有被捕獲的異常
- 01-10Java中的浮點(diǎn)數(shù)分析
- 01-10面向?qū)ο缶幊?Java中的抽象數(shù)據(jù)類型
- 01-10Windows+Apache+resin配置
- 01-10通過JDBC連接oracle數(shù)據(jù)庫的十大技巧


閱讀排行
本欄相關(guān)
- 01-10Java咖啡館(1)——嘆咖啡
- 01-10JVM的垃圾回收機(jī)制詳解和調(diào)優(yōu)
- 01-10Java Socket編程(三) 服務(wù)器Sockets
- 01-10Java進(jìn)階:Struts多模塊的技巧
- 01-10J2SE 1.5版本的新特性一覽
- 01-10Java Socket編程(一) Socket傳輸模式
- 01-10Java運(yùn)行時(shí)多態(tài)性的實(shí)現(xiàn)
- 01-10Java Socket編程(二) Java面向連接的類
- 01-10Java Socket編程(四) 重復(fù)和并發(fā)服務(wù)
- 01-10Java經(jīng)驗(yàn)點(diǎn)滴:處理沒有被捕獲的異常
隨機(jī)閱讀
- 08-05織夢dedecms什么時(shí)候用欄目交叉功能?
- 01-10delphi制作wav文件的方法
- 08-05DEDE織夢data目錄下的sessions文件夾有什
- 01-10使用C語言求解撲克牌的順子及n個(gè)骰子
- 01-10C#中split用法實(shí)例總結(jié)
- 04-02jquery與jsp,用jquery
- 01-10SublimeText編譯C開發(fā)環(huán)境設(shè)置
- 01-11Mac OSX 打開原生自帶讀寫NTFS功能(圖文
- 08-05dedecms(織夢)副欄目數(shù)量限制代碼修改
- 01-11ajax實(shí)現(xiàn)頁面的局部加載