camel

没有类型的java
作为动态语言,groovy中所有的变量都是对象(类似于.net framework,所有对象继承自java.lang.Object),在声明一个变量时,groovy不要求强制类型声明,仅仅要求变量名前使用关键字def(从groovy jsr 1开始,在以前的版本中,甚至连def都不需要)。
修改main 方法中的代码:
def var="hello world"
println var
println var.class
你可以看到程序最后输出了var的实际类型为:java.lang.String
作为例外,方法参数和循环变量的声明不需要def

不需要的public

你可以把main方法前面的public去掉,实际上,groovy中默认的修饰符就是public,所以public修饰符你根本就不需要写,这点跟java不一样。

3、  不需要的语句结束符

Groovy中没有语句结束符,当然为了与java保持一致性,你也可以使用;号作为语句结束符。在前面的每一句代码后面加上;号结束,程序同样正常运行(为了接受java程序员的顽固习惯)

4、  字符串连接符

java一样,如果你需要把一个字符串写在多行里,可以使用+号连接字符串。代码可以这样写:

       def var="hello "+

       "world"+

       ",groovy!"

当然更groovy的写法是:

       def var="""hello

       world

       groovy!"""

三个号之间不在需要+号进行连接(不过字符串中的格式符都会被保留,包括回车和tab

、  循环
删除整个源文件内容,用以下代码替代:
       def var="hello "+
       "world"+
       ",groovy!"
       def repeat(val){
            for(i = 0; i < 5; i++){
             println val
            }
       }
       repeat(var)
输出:
hello world,groovy!
hello world,groovy!
hello world,groovy!
hello world,groovy!
hello world,groovy!
注意循环变量i前面没有def。当然也没有java中常见的int,但如果你非要加上int也不会有错,因为从Groovy1.1beta2之后开始(不包括1.1beta2),groovy开始支持java经典的for循环写法。
此外,上面的for语句还可以写成:
            for(i in 0..5)
这样的结果是一样的。     
7、  String 和 Gstring
除了标准的java.lang.String以外(用’号括住),groovy还支持Gstring字符串类型(用“号括住)。把上面的for循环中的语句改成:
             println "This is ${i}:${val}"
运行一下,你就会明白什么是Gstring。

集合
Groovy支持最常见的两个java集合:java.util.Collection和java.util.Map。前面所说的范围实际也是集合的一种(java.util.List)。
(1) Collection
Groovy 中这样来定义一个Collection:
def collect=["a","b","c"]
除了声明时往集合中添加元素外,还可以用以下方式向集合中添加元素:
collect.add(1);
       collect<<"come on";
       collect[collect.size()]=100.0
Collection使用类似数组下标的方式进行检索:
       println collect[collect.size()-1]
       println collect[5]
groovy支持负索引:
println collect[-1]      //索引其倒数第1个元素
       println collect[-2]      //索引其倒数第2个元素

groovy支持负索引:
println collect[-1]      //索引其倒数第1个元素
       println collect[-2]      //索引其倒数第2个元素
Collection支持集合运算:
collect=collect+5        //在集合中添加元素5
       println collect[collect.size()-1]
       collect=collect-'a'         //在集合中减去元素a(第1个)
       println collect[0]          //现在第1个元素变成b了
同样地,你可以往集合中添加另一个集合或删除一个集合:
       collect=collect-collect[0..4]   //把集合中的前5个元素去掉
       println collect[0]   //现在集合中仅有一个元素,即原来的最后一个元素
       println collect[-1]  //也可以用负索引,证明最后一个元素就是第一个元素
(2) Map
Map是“键-值”对的集合,在groovy中,键不一定是String,可以是任何对象(实际上Groovy中的Map就是java.util.Linke dHashMap)。
如此可以定义一个Map:
       def map=['name':'john','age':14,'sex':'boy']
添加项:
       map=map+['weight':25]       //添加john的体重
       map.put('length',1.27)      //添加john的身高
       map.father='Keller'         //添加john的父亲
可以用两种方式检索值:
       println map['father']       //通过key作为下标索引
       println map.length          //通过key作为成员名索引

闭包(Closure)
闭包是用{符号括起来的代码块,它可以被单独运行或调用,也可以被命名。类似‘匿名类’或内联函数的概念。
闭包中最常见的应用是对集合进行迭代,下面定义了3个闭包对map进行了迭代:
       map.each({key,value->    //key,value两个参数用于接受每个元素的键/值
       println "$key:$value"})
       map.each{println it}     //it是一个关键字,代表map集合的每个元素
       map.each({ println it.getKey()+"-->"+it.getValue()})
除了用于迭代之外,闭包也可以单独定义:
def say={word->
           println "Hi,$word!"
       }
调用:
say('groovy')
       say.call('groovy&grails')
输出:
Hi,groovy!
Hi,groovy&grails!

Camel中的Exchange是路由期间的消息容器。

Exchange也为系统之间的各种类型的交互提供支持,也称为消息交换模式(MEP)。

MEP用于区分单向和请求 - 响应消息传递风格。

Camel的Exchange所拥有的模式属性,可以是

■ InOnly - 单向消息(也称为事件消息)。例如,JMS消息传递通常是单向消息传递。

■ InOut - 请求 - 响应消息。例如,基于HTTP的传输通常是请求回复,客户端请求检索网页,等待服务器的回复

Pattern:

 

 

Exception:

如果在处理器Processor处理过程中,开发人员需要抛出异常并终止整个消息路由的执行过程,可以通过设置Exchange中的exception属性实现

 

 

 

Exchange中的Message

Exchange中还有两个重要属性 inMessage 和 outMessage。

这两个属性分别代表Exchange在某个处理元素(处理器、表达式等)上的输入消息和输出消息。

 

当控制端点和处理器、处理器和处理器之间的Message在Exchange中传递时,Exchange会自动将上一个元素的输出值作为这个元素的输入值进行使用。

如果再上一个处理器中,开发人员没有在Exchange中设置任何out message内容(即Exchange中out属性为null),那么上一个处理器中的in message 内容将作为这个处理器的in message内容。

 

需要注意一下:

在DefaultExchange类中关于getOut()方法的实现,有这样的代码片段:

......
public Message getOut() {
    // lazy create
    if (out == null) {
        out = (in != null && in instanceof MessageSupport)
            ? ((MessageSupport)in).newInstance() : new DefaultMessage();
        configureMessage(out);
    }
    return out;
}
......
所以在处理器中对out message属性赋值,并不需要开发人员明确的"new"一个Message对象。

只需要调用getOut()方法,就可以完成out message属性赋值。

 

我们看下原博中的一个栗子:

以下路由代码片段在fromEndpoint后,连续进入两个Processor处理器,且Exchange的ExchangePattern为InOut。

我们来观察从第一个处理处理完后,到第二个处理收到消息时Exchange对象中的各个属性产生的变化:

......
from("jetty:http://0.0.0.0:8282/doHelloWorld")
.process(new HttpProcessor())
.process(new OtherProcessor())
......

第一个HttpProcessor执行末尾时,Exchange中的属性

 

上图显示了当前内存区域中,Exchange对象的id为452,fromEndpoint属性是一个JettyHttpEndpoint的实例,对象id为479。

注意两个重要的inMessage和outMessage,它们分别是HttpMessage的实例(对象id467)和DefaultMessage的实例(对象id476),

这里说明一下无论是HttpMessage还是DefaultMessage,它们都是org.apache.camel.Message接口的实现。

 

outMessage中的body部分存储了一个字符串信息,我们随后验证一下信息在下一个OtherProcessor处理器中的记录方式。

 

第二个OtherProcessor开始执行时,Exchange中的属性

 

可以看到HttpProcessor处理器中outMessage的Message对象作为了这个OtherProcessor处理器的inMessage属性,

对象的id编号都是476,说明他们使用的内存区域都是相同的,是同一个对象。

Excahnge对象的其它信息也从HttpProcessor处理器原封不动的传递到了OtherProcessor处理器。

 

每一个Message(无论是inMessage还是outMessage)对象主要包括四个属性:MessageID、Header、Body、Attachment。

 

MessageID:

在系统开发阶段,提供给开发人员使用的,标示信息对象唯一性的属性,这个属性可以没有值。

 

Header:

消息结构中的"头部"信息,在这个属性中的信息采用K-V的方式进行存储,并可以随着Message对象的传递将信息带到下一个参与路由的元素中。

 

需要注意的是,在org.apache.camel.impl.DefaultMessage中对headers属性的实现是一个名叫org.apache.camel.util.CaseInsensitiveMap的类。

看这个类的名字就知道:headers属性的特点是忽略大小写。也就是说:

......
outMessage.setHeader("testHeader", "headerValue");
outMessage.setHeader("TESTHEADER", "headerValue");
outMessage.setHeader("testheader", "HEADERVALUE");
......
以上代码片段设置后,Message中的Headers属性只有一个K-V键值对信息,且以最后一次设置的testheader为准。

 

Body:

Message的业务信息内容存放在这里。

 

Attachement:

Message中使用attachement属性存储各种文件内容信息,以便这些文件内容在Camel路由的各个元素间进行流转。

attachement同样使用K-V键值对形式进行文件内容的存储。

但不同的是,这里的V是一个javax.activation.DataHandler类型的对象。

 

 

 

Processor处理器

Camel中另一个重要的元素是Processor处理器,它用于接收从控制端点、路由选择条件又或者另一个处理器的Exchange中传来的消息,并进行处理。

Camel核心包和各个Plugin组件都提供了很多Processor的实现,开发人员也可以通过实现org.apache.camel.Processor接口自定义处理器(后者是通常做法)。

 

既然是做编码,那么我们自然可以在自定义的Processor处理器中做很多事情。

这些事情可能包括处理业务逻辑、建立数据库连接去做业务数据存储、建立和某个第三方业务系统的RPC连接,但是我们一般不会那样做——那是Endpoint的工作。

Processor处理器中最主要的工作是进行业务数据格式的转换和中间数据的临时存储。

这样做是因为Processor处理器是Camel编排的路由中,主要进行Exchange输入输出消息交换的地方。

 

不过开发人员当然可以在Processor处理器中连接数据库。

例如开发人员需要根据上一个Endpoint中携带的“订单编号前缀”信息,在Processor处理器中连接到一个独立的数据库中(或者缓存服务中)查找其对应的路由信息,以便动态决定下一个路由路径。

由于Camel支持和Java语言的spring框架无缝集成,所以要在Processor处理器中操作数据库只需要进行非常简单的配置。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值