Camel中的重要概念

Endpoint:即节点,即消息经过的地方

Camel支持的EndPoint

1.JMS队列

2.web service

3.文件

4.FTP服务

5.email地址

6.POJO

在基于Camel的应用中,你会创建一些EndPoint然后用路由将这些EndPoint连接起来。Camel定义了一个名这EndPoint的接口,每一个Camel支持的EndPoint都有一个类实现了该EndPoint接口,Camel提供了单独的Javadoc继承树为Camel支持的每一种通信技术。

CamelContext

一个CamelContext对象代表了Camel的运行时系统,典型的你会有一个CamelContext对象在一个应用中,一个典型的应用遵循下面的步骤:

1.创建一个CamelContext对象

2.添加Endpoints和可能的组件到该CamelContext对象中

3.添加路由到该CamelContext对象中去连接这些EndPoint

4.调用CamelContext的start()方法,这样会启动Camel内部线程,这些线程用于处理EndPoint中消息的发送,接收与处理

5.调用CamelContext的stop()方法,这样将会停止所有Camel内部线程

注意:CamelContext.start()方法,并不会无限制阻塞下去,而是该方法会为每一个组件与Endpoint开始内部线程然后返回。同理,CamelContext.stop()方法会等待每一个组件与EndPoint的所有内部线程都终止后该方法才会返回。

如果在你的应用中没有调用CamelContext.start()方法,消息将不会被处理因为内部线程还没有被创建。如果在停止你的应用之前你没有调用CamelContext.stop()方法,应用可能会以一种不一致的状态停止。如果在JUnit测试中没调用CamelContext.stop()方法,测试可能会因为消息没有机会完全被处理而失败。

CamelTemplate

Camel以前有一个叫CamelClient的类,但是现在已经更名为CamelTemplate了,这样做的原因是迎合其它开源项目的命名约定,如Spring中的TransactionTemplate和JmsTemplate。

CamelTemplate类是一个包装了CamelContext的精简类,它有发送消息或Exchange到EndPoint的方法。这样就提供了一个输入消息到源Endpoint的途径,所以消息会沿着路由移动直到目的Endpoint。

Component

Component是一个容易术语,用EndpointFactory可能会更恰当因为Component是一个用于创建EndPoint实例的工厂。例如,如果一个基于Camel的应用使用了多个JMS queues,这时应用将会创建一个JmsComponent(实现了Component接口)类的实例,然后应用调用其createEndpoint()方法来创建一个EndPoint实例。实际上,应用级别的代码不会直接调用Component.createEndpoint()方法,而通常会调用CamelContext.getEndpoint()方法来代替,该方法内部,CamelContext对象查找到相应的Component然后调用它的createEndpoint()方法。例如下面的代码:

myCamelContext.getEndpoint("pop3://[email protected]?password=myPassword");

getEndpoint()方法的参数是一个URI,这个URI的前缀指明了这个组件的名称(name)。在内部,CamelContext对象拥有一个映射名称到组件的映射表。在上面的例子的URI中,CamelContext对象很可能将pop3前缀映射到一个MailComponent的实例。然后CamelContext对象调用这个MailComponent对象的createEndpoint("pop3://[email protected]?password=myPassword")方法。这个createEndpoint()方法将会把这个URI分隔成若干个部分然后使用这些部分来配置这个EndPoint对象。

在以前的段落中,提到了一个CamelContext对象拥有一个Component name到Component对象的映射。这就引出了一个问题,这张映射表如何来映射这些组件,有两种方式:

一是应用级别调用CamelContext.addComponent(String componentName, Component component)方法。下面这个例子将一个MailComponent对象用三个不同的名称注册在映射表中:

Component mailComponent = new org.apache.camel.component.mail.MailComponent();
myCamelContext.addComponent("pop3", mailComponent);
myCamelContext.addComponent("imap", mailComponent);
myCamelContext.addComponent("smtp", mailComponent);</span>

二是(更好)让CamelContext对象中的映射表延迟初始化,这种方式要开发者实现Component接口时遵循一定的约定。例如,假设你写了个名为com.example.myproject.FooComponent的类,而且你想让Camel自动以"foo"来进行识别。为了达到这样的目的你必须写一个叫"META-INF/services/org/apache/camel/component/foo"的Properties文件(没有.properties文件后缀),该Properties只有一个条目class,该条目的值就是该组件的全路径名:

class=com.example.myproject.FooComponent

如果你还让com.example.myproject.FooComponent以name "bar"识别,你还得写另外一个properties文件(文件名为bar)在相同的目录中,而且含有相同的内容。一旦你写了这些Properties文件,你创建的jar包中含有com.example.myproject.FooComponent以及相应的Properties文件,并且这个jar包加入到了CLASSPATH下。这样在应用级别就可以用代码在CamelContext对象上调用createEndpoint("foo:...")方法,Camel将在CLASSPATH中找到"foo"properties文件,获取该文件中class条目的值,然后使用反射技术创建指定类的实例。

Camel支持多种开箱即用通信技术,该开箱即用支持由多个实现了Component接口的类以及它们相应的properties文件来实现,以供CamelContext对象来构建这张named Component对象映射表。

在前面的部分我给出了一个如下例子,调用CamelContext.getEndpoint().

myCamelContext.getEndpoint("pop3://[email protected]?password=myPassword");

当我第一次给出这个例子时,我说getEndpoint()方法的参数是一个URI,我之所以那样说的原因是Camel的在线帮助文档和Camel的源代码都声称这是一个URI。而实际上,这个参数严格上来说是一个URL。这是因为当Camel从参数中抽取component name时,它第一步找":",这是一个简单算法。要理解其原因,就得回到Section4.4("The meaning of URL,URI,URN and IRI"),一个URI可能是一个URL或者是一个URN,考虑下面的getEndpoint()方法调用:

myCamelContext.getEndpoint("pop3:...");

myCamelContext.getEndpoint("jms:...");

myCamelContext.getEndpoint("urn:foo:...");

myCamelContext.getEndpoint("urn:bar:...");

在上面的例子中Camel标识这些组件用的名称分别是:"pop3","jms","urn"和"urn".如果后两个组件用"urn:foo"和"urn:bar"来标识可能会更贴切,实际上用的是"urn"和"urn"(只取第一个":"号前面部分作为Component name)。所以在实际应用中你必须用一个URL("<schema>:...形式")来标识一个endpoint而不是用一个URN("urn:<schema>:..."形式)。因为这里缺少对URN的更多支持所以getEndpoint()方法的参数是一个URL而不是所谓的URI。

Message and Exchange

Message接口是一个消息的抽象,比如说一个请求,一个回复或者一个例外消息。

Camel为每一个支持的通信技术提供了Message接口的相应实现类。例如,JmsMessage类提供了JMS-specific的Message接口实现。公共接口Message提供了getter与setter方法来访问message id,消息休和消息头字段。

Exchange接口是消息交换的抽象,一个请求消息和它相应的应答或者例外消息。在Camel技术中,请求,应答和例外消息分别被称为输入(in),输出(out),和错误(fault)消息。

Camel也为第一种支持的通信技术提供了Exchange接口的实现。例如,JmsExchange类提供了JMS-specific的Exchange接口实现。Exchange公共接口的API有很大的局限性,这是有意设计成这样的。因为每一个实现Exchange接口的实现类将会提供具体的技术相关的方法。

在应用级别程序员几乎不会直接访问Exchange接口(或者其实现类)。然而,在Cmael的很多类是泛型类are instantiated on(a class that implements)Exchange。这样做的原因是Exchange接口出现在了许多泛型的类和方法中。

Processor

Processor接口代表一个可以处理消息的类,其签名如下:

package org.apache.camel;

public interface Processor {

void process(Exchange exchange) throws Exception;

}

注意process()方法的参数是一个Exchange对象而不是一个Message对象。这样提供了扩展性。例如,一个实现类的process()方法初始可能会调用exchange.getIn()方法得到输入消息并且进行处理。如果在处理的过程中发生了错误,该方法可以调用exchange.setException()方法。一个应用级别的开发者可能会开发一个类实现Process接口来执行一个业务逻辑,然后在Camel类库中已经有很多类实现了Processor接口来支持EIP book中的设计模式。例如,ChoiceProcessor实现了消息的路由

,它使用一种级联的if-then-else语句来路由一个来自队列的消息到多个输出队列中的一个。另外一个例子是FilterProcessor类,它将会抛弃那些不满足条件的消息。

Routes, RouteBuilders and Java DSL

一个路由是消息从一个输入队列一步一步地,通过任意类型的决断移动到一个目的队列。Camel为应用提供了两种方式供开发者指定路由,一种是将路由信息配置在一个XML文件当中,另一种方式是Camel中所谓的Java DSL(domain-specific language)。

Introduction to Java DSL

对很多人来说"domain-specific language"词语意味着一个编译器或解释器可以处理一个包含了关键字和具体语义的输入文件到一个特定的域中。但这不是Camel所采用的方式。Camel文档中坚持用“Java DSL”代替“DSL”,但这也不能完全避免潜在的混淆。Camel的“Java DSL”是一个类库,可以以一种与DSL很类似的方式使用,除非它包含很少的java语法。你可以看下面的例子,后面的注释解释了这个例子的构成。

RouteBuilder builder = new RouteBuilder() {
    public void configure() {
        from("queue:a").filter(header("foo").isEqualTo("bar")).to("queue:b");
        from("queue:c").choice()
                .when(header("foo").isEqualTo("bar")).to("queue:d")
                .when(header("foo").isEqualTo("cheese")).to("queue:e")
                .otherwise().to("queue:f");
    }
};
CamelContext myCamelContext = new DefaultCamelContext();
myCamelContext.addRoutes(builder);</span>

第一行创建了一个RouteBuilder的匿名子类对象,覆盖了configure()方法。

The CamelContext.addRoutes(RouterBuilder builder)方法中调用了builder.setContext(this),所以RouterBuilder对象知道它自己关联的CamelContext对象,然后调用builder.configure()方法,configure()方法体调用的例如from(),filter(),choice(),when()isEqualTo(),otherwise()和to(). RouteBuilder.from(String uri)方法调用CamelContext对象的getEndpoint(uri),并且与RouteBuilder对象一起查找指定的Endpoint,然后放置一个FromBuilder包装器到这个Endpoint。FromBuilder.filter(Predicate
predicate)方法为Predicate(条件)创建一个FilterProcessor对象,从header("foo").isEqualTo("bar")语句构建而来。这样上些操作递增地构造了一个Route对象并且将它添加进CamelContext。

时间: 2024-10-09 08:33:59

Camel中的重要概念的相关文章

数据库中一些基本概念的深入理解

1.怎样理解事务的一致性 一致性就是一个这样的东西,一致性对于不同的应用领域有着不同的定义,因为它就是按照业务规则来说明这个是一致的,那个是不一致的,这个角度上讲,一致性就是一个系统的状态,一个合理的状态.而合理则表现在这个状态是否符合业务规则.例如:转账业务中合理的状态就是,转出和转入帐户必须出入相等,如果不等那就意味着不合理,也就是不一致,有时候我们很容易就能把它定为"守恒一致性",也就是说总体来说什么也不多,什么也不少就是一致性.而这个规则能够使用于其他的义务吗?我们不能说不能,

Python中类型的概念(一)

本课程主要介绍6种Python语言中的类型:数字类型.字符串类型.元组类型.列表类型文件类型.字典类型 1.数字类型 Python语言包括三种数字类型:整数类型.浮点数类型.复数类型 (1)整数类型 与数学中的整数概念一致,没有取值范围限制 pow(x, y)函数:计算xy. (通过指数函数,可以看出,python语言整数类型没有范围限制) (0x, 0X开头表示16进制数) (0b, 0B开头表示2进制数 ) (0o, 0O开头表示8进制数) (2)浮点数类型 带有小数点及小数的数字 Pyth

javascript (js)中的基本概念

1. 基本数据类型 1.1 number (数字)在js中没有整形和浮点型的区分,所有的数字都是浮点型标识, 采用64位的浮点格式来表示数字.如果数字类型用在字符串连接表达式中,则会自动转换成字符串, 在JS中表示16进制通过在数字前加"0x"或"0X"(零). 1.2 string (字符串)字符串类型是实用单引号('')或双引号("")括起来的unicode字符序列, 一些特殊的字符可以通过转义符来标识.如果字符串用在数字表达式环境中,字符串

关于一些 MYSQL中的字符集概念

最近遇到mysql乱码的问题,找了些资料,先保存,后面慢慢总结自己的处理方法. 笔记: 问题环境总结: 1.前台php代码没有改变 2.原数据库,所有表的都是utf8 mysql> show variables like '%char%';+--------------------------+----------------------------------+| Variable_name            | Value                            |+---

[Elasticsearch] 聚合中的重要概念 - Buckets(桶)及Metrics(指标)

[Elasticsearch] 聚合中的重要概念 - Buckets(桶)及Metrics(指标) 2015-01-04 来源: http://blog.csdn.net/dm_vincent/article/details/42387161 本章翻译自Elasticsearch官方指南的Aggregations-High-level Concepts一章. 高层概念(High-Level Concepts) 和查询DSL一样,聚合(Aggregations)也拥有一种可组合(Composabl

java中的引用类型概念

转自:http://blog.sina.com.cn/s/[email protected]陌上蜗牛 1.什么是引用类型     引用类型(reference type)指向一个对象,不是原始值,指向对象的变量是引用变量. 在java里面除去基本数据类型的其它类型都是引用数据类型,自己定义的class类都是引用类型,可以像基本类型一样使用.     示例如下:     public class MyDate {         private int day = 8;         priva

Mycat中的核心概念

Mycat中的核心概念 1.数据库中间件 Mycat 是一个开源的分布式数据库系统,但是由于真正的数据库需要存储引擎,而 Mycat 并没有 存储引擎,所以并不是完全意义的分布式数据库系统.Mycat 是数据库中间件,就是介于数据库与应用之间,进行数据处理与交互的中间服务.有了数据库中间件,应用只需要集中与业务处理,大量的通用的数据聚合,事务,数据源切换都由中间件来处理,中间件的性能与处理能力将直接决定应用的读写性能,所以一款好的数据库中间件至关重要. 2.逻辑库(schema) 对实际应用来说

Lua语言基础汇总(10) -- Lua中的环境概念

前言 Lua将其所有的全局变量保存在一个常规的table中,这个table称为“环境”.这种组织结构的优点在于,其一,不需要再为全局变量创造一种新的数据结构,因此简化了Lua的内部实现:另一个优点是,可以像其他table一样操作这个table.为了便于实施这种操作,Lua将环境table自身保存在一个全局变量_G中.例如,我们可以使用以下代码打印当前环境中所有全局变量的名称. 1 for n in pairs(_G) do print(n) end 在你的电脑上运行一下以上代码,看看结果. 全局

【转】简单了介绍js中的一些概念(词法结构) 和 数据类型(部分)。

1 , javascript字符集: javascript采用的是Unicode字符集编码. 为什么要采用这个编码呢? 原因很简单,16位的Unicode编码可以表示地球人的任何书面语言.这是语言 国际化的一个重要特征.(大家也许见过用中文写脚本,比如:function 我的函数() {} ); Javascript中每个字符都是用2个字节表示的.(因为是16位编码) 2 ,大小写敏感: js是一种区分大小写的语言. 注意下:以前我也犯过的错误. HTML是不区分大小写的.经常看见有人这么写,