??xml version="1.0" encoding="utf-8" standalone="yes"?> MinaTutorialInChinese
]]>
http://man.lupaworld.com/content/develop/hello/HelloWorld.shtml
]]>
com.opensymphony.xwork.config.ConfigurationException: Caught exception while loading file xwork.xml
with nested exception
org.xml.sax.SAXParseException: Element type "global-exception-mappings" must be declared.
头疼了几个小时解决不了,不得不求助飞云小?br />飞云侠一出手果然不同Q马上定位了问题所?br />是q句Q?br />
原来虽然几次升webwork.jarQ但是xwork.xml的DTD解析q是用的原来的DTDQ顶多就是改了DTD的地址Q也是这?br /> "http://www.opensymphony.com/xwork/xwork-1.1.dtd">
"http://www.opensymphony.com/xwork/xwork-1.1.1.dtd">
而实际上解析DTD是靠的前面那?br />>
<!DOCTYPE xwork PUBLIC "-//OpenSymphony Group//XWork 1.0//EN"
>
]]>
First for all, QuickServer is licensed as LGPL, and MINA as ASL
从我个h角度而言Q去q看qQuickServer的源码,我在目中采用的每一个框架或cd都会做综合评P通常不会是一个原因导致我采用或没有采用某个库或框Ӟ具体最后没有采用QuickServer的原因忘CQ但是当时给我的M感觉是,QuickServer虽然很方便,但不会让我在架构上得到新的好处。而它最大的优点则是Q支持JDK1.3Q如果没记错的话Q,另外是License的问?BR>
下面看一看来自TrusinLee的评论:
Thank for the information about another network application framework. I found a few differences:
* QuickServer supports blocking mode. (MINA supports only non-blocking mode, but you can make your operation block at your will.)
* QuickServer provides GUI-based admin. (MINA doesn't have one yet, but will have full JMX support soon, which is a standard.)
* QuickServer uses java.util.logging. (MINA uses SLF4J, which is a safe replacement of commons-logging.)
* QuickServer uses its own XML settings. (MINA provides Spring framework integration instead.)
* QuickServer can specify maximum number of clients allowed. (MINA can do this using a filter, but not implemented by default. Of course, this will be implemented as an overload prevention filter.)
* QuickServer team has one crew. (MINA has three crews.)
* QuickServer project started in 2003. (MINA started in 2005.)
* QuickServer has a difference event handler interface from MINA. (You'll have to compare it by yourself. IMHO, MINA has one simple enough handler which covers all QuickServer provides.)
* QuickServer doesn't support UDP at all. (MINA does)
* QuickServer doesn't support client-side API at all. (MINA does)
* QuickServer integrated authentication and text protocol in its core. (MINA didn't and they are considered as a cross-cutting concern that a filter should take care of. IMHO, MINA is more extensible here.)
至于对MINA更详l的介绍Q可以看看我d译的MINA的Tutorial
MINA的应用,在MINA的Testimonials中有两个目Q?BR>开源Flash serverQ?A >red5
http://ludonet.leonardo.it/的game server
q有Q就是MINA所在的目QApache?A >LDAP
]]>
开发一个基于消息的解决Ҏ(gu)是不Ҏ(gu)的事情,在生产中操作q样一个品同样也是一个挑战:一个基于消息的集成解决Ҏ(gu)一天可以生、\由和转换成千上万的消息。我们不得不处理异常、效率瓶颈或改变合作pȝ。而ؓ了事情变得更加有挑战性,lgl常被分布在不同的^台和机器上,甚至位于不同的地理位|?/SPAN>
System Management包含以下几种模式
l Control Bus
l Detour
l Wire Tap
l Message History
l Message Store
l Smart Proxy
l Test Message
l Channel Purger
除了与生据来的复杂性、分布式集成的规模以及个性化的应用之外,低耦合的架构得测试和debug变得更加困难?/SPAN>Martin Fowler这个症状称为?SPAN style="COLOR: red">架构师的梦想Q开发者的梦魇”。低耦合的架构原则以及间接的依赖于外部系l提供了灉|性。然而,试一个消息生产者不了解消息消费者的pȝ可能会是一个挑战。另外异步的和时间相关的消息使得事情变的更加复杂。D例来_消息Ҏ(gu)可能被设计没有被成消息生产者者必M接受者那里得C个回应。同L消息基础设施通常保证传输消息Q但不能保证传输旉。这是的开发基于消息传送结果的试用例变得困难?/SPAN>
当监控一个消息解x案,我们可以在两个抽象层面上跟踪消息。一个典型的pȝ理Ҏ(gu)监控多少消息被发送或者它多长旉得到一个被处理的消息。这些监控方案不查消息数据,除了可能会检查消息头中的几个字段Q比如消息标识或者消息历Ԍ。与之相对的Q?/SPAN>BAMQ?/SPAN>business activity monitoringQ方案聚焦于包含在消息中的有效数据,举例来说Q发生在q去一时的所有订单的金额?/SPAN>System Management中的很多模式都够通用q可以用在以上两个目的中Q监控消息头或者消息内容)。然而,׃BAM本n是一个新领域Qƈ且需要从数据仓库中获得很多数据(有些我们Ҏ(gu)没有涉及到Q,我们军_在系l管理的内容中讨些模式?/SPAN>
pȝ理模式被设计用于ؓ保持一个基于消息的复杂pȝ的运转所提出的需求ƈ提供工具?/SPAN>System Management的模式涉及三个种c:监控和控Ӟ观察和分析消息流量,试和调?/SPAN>?/SPAN>
监控和控?/SPAN>
一?/SPAN>Control Bus提供一个单独的控制Ҏ(gu)对一个分布式Ҏ(gu)q行监控和管理。它?yu)多个组件连接到一个中心管理控制台Q这里可以显C每个组件的状态ƈ且监控通过每个lg的消息流量。控制台同时也可以用于发送控制命令给lgQ比如,转变消息?/SPAN>
我们可能惌在\由消息时d附加的步骤,比如验证或者日志。由于这些步骤可能效率降低Q所以我们可以通过Control Bus来控制他们开兟뀂一?/SPAN>Detour为我们提供这U能力?/SPAN>
观察和分析消息流?/SPAN>
有时我们惌在不影响主要消息的情况下观察消息的内容。一?/SPAN>Wire Tap允许我们接入到消息流中?/SPAN>
当我们调试一个基于消息的pȝQ知道一个特定的消息在哪使很有帮助的?/SPAN>Message History保留一个消息访问过的所有组件的日志Q而不需要增加组仉的依赖?/SPAN>
然?/SPAN>Message History依赖于单独的消息Q一个中心的Message Store可以提供一个穿系l的每个消息的完整记录。结?/SPAN>Message HistoryQ?/SPAN>Message Store可以分析所有消息穿q系l的可能路径?/SPAN>
Wire Tap, Message History, ?/SPAN>Message Store帮助我们分析异步的消息流。ؓ了跟t发送到h-应答service的消息,我们需要在消息中插入一?/SPAN>Smart Proxy?/SPAN>
试和调?/SPAN>
在部|前试一个消息系l是一个非常好的注意。但是测试不应该停止在部|前。你应该有能力验证正在运行的消息pȝq行持箋的运行正常。你可以周期性的发送一?/SPAN>Test Message到系l中q证结果?/SPAN>
当一个组件失败或者运行不正常Q它可以单的l止Qƈ攑ּ一?/SPAN>channel中的剩余消息。在试期间q是很有用的。一?/SPAN>Channel Purger可以为我们做q些?/SPAN>
l Messaging Gateway
l Messaging Mapper
l Transactional Client
l Polling Consumer
l Event-Driven Consumer
l Competing Consumers
l Message Dispatcher
l Selective Consumer
l Durable Subscriber
l Idempotent Receiver
l Service Activator
发送和接收模式
有些endpoint模式既可以用在发送方也可以用在接受斏V它们描qC个应用连接一个消息系l的一般情c?/SPAN>
包装消息代码 Q?/SPAN> 一个应用不应该意识到正在用消息同另外一个应用程序通讯Q大多数应用代码应该在不知道message的情况下被编写。在应用集成的地方,应该有一个薄薄的一层代码来执行应用的集成部分。当集成是由消息实现的,q层应用连接到消息pȝ的代码称Z?/SPAN>Message Gateway
数据转换 Q?/SPAN> 当发送者和接受者用不同的数据格式Q或者不同的消息格式Q支持不同的发送和接收者)Q在q种情况下,使用一?/SPAN>Message Mapper来在应用格式和消息格式之间{换数据?/SPAN>
外部控制的事?/SPAN> Q?/SPAN> 消息pȝ在内部和外部使用事务Q默认的Q每个发送和接收Ҏ(gu)在他们自q事务中运行?/SPAN>Message生者和消费者应可选的使用一?/SPAN>Transactional Client来控制事务,当你需要将几个消息一起发送伙通过其他事务服务整理消息时是很有用的?/SPAN>
消息消费者模?/SPAN>
其他endpoint模式只适用于消息消费者,发送消息是单的。棘手的问题是决定一个消息应该何时发送,它应包含什么,以及怎样它送到接受?/SPAN> Q?/SPAN> q是Z么我们有很多消息l构模式 Q?/SPAN> 但是一旦消息被构徏Q发送它是很Ҏ(gu)的。另一斚wQ接收消?/SPAN> Q?/SPAN> 很麻烦。因此许?/SPAN>endpoint模式是关于接收消息的?/SPAN>
接收消息的一个最重要的主题就是流量控Ӟ一个应用控Ӟ或者调节它消费消息的速度。一个潜在的问题是Q?/SPAN>server都面临着大量的客Lh会其超载。通过q程q程调用Q?/SPAN>RPIQ,server几乎受到客户端调用的支配。同LQ通过消息Q?/SPAN>server不能控制客户端发送请求的速度 Q?/SPAN> 但是server可是控制它处理这些请求的速度。应用不必像消息pȝ传送消息那么快的接收ƈ处理消息Q用一?/SPAN>Message Channel可以使它在一个可接收的速率上处理消息。然而,当消息积累太多,?/SPAN>serverq有资源可以处理的更快,它可以用同?/SPAN>message消费者来加快速度。所以用这些消息消费者模式可以让你的应用速度控制在它可以承受的范围?/SPAN>
许多消息消费者模式都是成对出现的Q你可以任选一个用?/SPAN>
同步或异步接受?/SPAN> Q?/SPAN> 可以使用轮询消费者或一个事仉动消费者。轮询提供最好的量控制Q因为如?/SPAN>server忙,则它不再l箋轮询消息Q所?/SPAN>message阻塞在队列。事仉动的消费者們于消息到达便触发处理Q所以有可能会server蝲Q但是每个消费者每ơ只处理一个消息,所以限制消费者的数量可以有效的控制消贚w度?/SPAN>
消息分派 vs 消息获取 Q?/SPAN> 另外一个二选一的模式是一堆消费者如何处理一堆消息。如果每个消费者获得一个消息,他们可以q行的处理消息。最单的Ҏ(gu)?/SPAN>Competing ConsumersQ也是一个点对点?/SPAN>channel有多个消费者。每个都可能获得M消息Q消息系l的实现军_那个消费者获得消息。如果你x制消息到消费者的匚wq程Q?/SPAN>Message Dispatcher?/SPAN>q时只有一个消费者接收消息,但是委z消息到一个执行者去处理。一个应用程序可以通过限制消费者或执行者的数量来控制流量。当Ӟ分派?/SPAN>Message Dispatcher也可以实C个流量控制行为?/SPAN>
接收所有消息或者过?/SPAN> Q?/SPAN> 默认的,M到达一?/SPAN>Message Channel的消息对于监听着q个channel?/SPAN>Message Endpoint都是可用的。然而有些消费者ƈ不打处?/SPAN>channel上的M消息Q而是希望只处理其中几U。这样一个识别的消费者可以用一?/SPAN>Selective Consumer来描q它?yu)接收什么类型的消息。然后消息系l将只将匚w的消息对该接受者描qCؓ可用?/SPAN>
当断开q接的时候订阅消?/SPAN> Q?/SPAN> Publish-Subscribe Channels带来的问题是Q如果一个消费者感兴趣一?/SPAN>channelQ但是现在网l是断开的怎么办?是不是一个未q接的应用将错过发布的消息,即它已l订阅过该消?/SPAN>?默认的,是的Q订阅只对连接的订阅者有效,Z使应用不会因接而错q订阅的消息Q要使用Durable Subscriber?/SPAN>
{幂 Q?/SPAN> 有时一个消息可能被传输不只一ơ,可能因ؓ消息pȝ不确定该消息是否已经被成功的传递过Q或者可能因?/SPAN>Message Channel?/SPAN>QoS被设|较低来提高效率。另一面的Q消息接受者认为每个消息只会被传输一ơ,q且当它们重复处理相同的消息Q它们会出错。一?/SPAN>Idempotent Receiver可以优雅的处理重复的消息Qƈ且阻止它们引h收者应用的发生错误?/SPAN>
同步或异步服?/SPAN> Q?/SPAN> 另外一个选择是一个应用应该暴露它?/SPAN>service为同步(RPIQ还是异步的Q?/SPAN>MessagingQ。不同的客户端可能喜Ƣ不同的方式Q不同的环境可能需要不同的方式。既然很N择Q就一起用。一?/SPAN>Service Activatorq接一?/SPAN>Message ChannelC个应用的同步服务以便当一个消息被接收Q?/SPAN>servicep调用。同步客L可以单的直接调用serviceQ异步客L可以通过发送消息调?/SPAN>service?/SPAN>
Message Endpoint的相关主?/SPAN>
Message Endpoint的另外一个重要主题是很难同其他模式共同应?/SPAN>Transactional Client?/SPAN>Event-Driven Consumer通常不能适当的在外部控制事务Q?/SPAN>Message Dispatcher也必d心的设计q个问题Q?/SPAN>Competing Consumers的事务也是个重大问题。最安全的?/SPAN>Transactional Client是用一个单独的Polling ConsumerQ但是这不会是一个o人满意的解决Ҏ(gu)?/SPAN>
q里特别要提到应该会保证成功?/SPAN>JMS风格?/SPAN>MDBQ?/SPAN>EJB的一U。一?/SPAN>MDB是一个消息消费者,它即使一?/SPAN>Event-Driven Consumer又是一个支?/SPAN>J2EE分布式事务的Transactional ClientQƈ且它可以作ؓCompeting Consumers动态的池化Q甚至作Z?/SPAN>Publish-Subscribe Channel。这是在一个自q应用中实现这些是一个困难且乏味的组合,但是q个功能作ؓ一?/SPAN>EJB容器的内建的功能被提供。(MDB框架如何实现的?本质上,容器通过一个动态改变大的可重用的执行者的U程池来实现了一?/SPAN>Message DispatcherQ在那里每个执行者自׃用自qsession和事务来消费消息。)
最后,紧记一个单独的Message Endpoint可以很好l合几个不同的模式。一l?/SPAN>Competing Consumers可以被作?/SPAN>Polling Consumers实现Q同时也可以是一?/SPAN>Selective Consumersq且可以作ؓ一?/SPAN>Service Activator调用一个应用的service?/SPAN>
一?/SPAN>Message Dispatcher可以是一?/SPAN>Event-Driven Consumer和一个?/SPAN>Messaging Mapper的一?/SPAN>Durable Subscriber。无Z?/SPAN>endpoint实现什么模式,它L一?/SPAN>Messaging Gateway。所以,不要考虑使用哪种模式 Q?/SPAN> 而要考虑如何l合他们。这是用模式解决问题的力所在?/SPAN>
要实C?/SPAN>Message Endpoint有很多选择?/SPAN>Message Endpoint模式用于解释q些选择是什么以及如何最好的使用它们?/SPAN>
通常Q通过消息pȝ集成的应用很有同样的消息格式。比如说Q一个帐务系l同一?/SPAN>CRMpȝ对客户对象是有着不同的概늚。基于这个,一个系l可能将消息存储在关p表中,另一个可能存储在文g中。集成已存在的系l通常意味着我们没有修改pȝ以便使他们更好的一起工作的自由。然而,集成Ҏ(gu)不得不协调和解决各种pȝ之间的不同?/SPAN>Message Translator模式提供了一个通用的解x案。这里解释几U特定的Message Translator?/SPAN>
Message Transformation包含以下几种模式Q?/SPAN>
l Envelope Wrapper
l Content Enricher
l Content Filter
l Claim Check
l Normalizer
l Canonical Data Model
大多数消息系l放|特定的需求在消息头的格式和内容中。我们包装有效数据到一?/SPAN>Envelope Wrapper中以适应消息基础设施的需求。如果消息需要穿q不同的消息基础设施Q可以结合多?/SPAN>Envelope Wrapper?/SPAN>
如果原始pȝ不能提供目标pȝ需要的数据域,可以使用一?/SPAN>Content Enricher。它可以查找~少的信息ƈ从已有数据中计算出它?/SPAN>Content Filter正好相反Q它从消息中删除不需要的数据?/SPAN>Claim Check也从消息中删除数据,但是它将存储他们以便以后取回?/SPAN>Normalizer多个不同格式的消息译成统一格式?/SPAN>
消除依赖
消息转换在集成中是一个很q话题?/SPAN>Message Channels?/SPAN>Message Routers可以通过消除应用必须知道另外一个应用的位置的需求从而解除应用间的基本依赖?/SPAN>
一个应用可以发送一个消息到Message Channel而不必担心谁来取出消息。然而消息格式增加了另外一U依赖。如果一个应用不得不消息格式化成另外一个应用的数据格式Q通过Message Channel解耦的说法像一个惟뀂接收系l的M改变或切换到另外一个接收系l都需要对发送应用进行改变?/SPAN>Message Translators可以帮助除去q种依赖?/SPAN>
元数据管?/SPAN>
消息从一个消息格式{换到另一个格式需要操作元数据 Q?/SPAN> 描述数据格式的数据?/SPAN>
元数据在两个q行pȝ之间的集成中扮演着非常重要的角艌Ӏ一个处理实际的消息数据Q另外一个处理元数据。许多用于处理消息数据的模式也同样可以管理元数据。比如说Q?/SPAN>Channel Adapter不仅可以从一个系l中U进和移出消息,q可以从一个外部应用中获取元数据,q将其加载到一个元数据仓库中。用这个仓库,集成开发者可以定义应用元数据?/SPAN>Canonical Data Model.之间的{换?/SPAN>
元数据集?/SPAN>
举例来说Q上面的图描qC两个需要交换客户信息的应用的集成。每个系l的客户数据的定义稍有不同。从A?/SPAN>B的消息需要{换一下才能被B接收。如?/SPAN>Channel Adapters可以抽取元数据的话,创徏一个{换将非常单。然后这个元数据可以被放入一个仓库,大大的简化了Message Translator的配|和验证。元数据可以被存储成不同的格式。通常XML消息使用XSD格式。其?/SPAN>EAI工具实现所有元数据格式Q但是允许管理员导入或导出到其他格式?/SPAN>
消息pȝ外的数据转换
q些转换模式l成的很多原则可以被应用于非消息集成。比如说Q?/SPAN>File Transfer可以执行pȝ间的转换工作。类似的Q?/SPAN>Remote Procedure Invocation必须使请求用要调用?/SPAN>service的格式,即应用本n的格式可能不同。典型的Q需要调用程序来执行转换。一些最成熟的{换引擎组成了ETL工具Q比?/SPAN>Informatica或?/SPAN>DataMirror。这些工具一般都一ơ{换大量的数据Q而不是{换单个消息?/SPAN>
Message System应专注于几种基本?/SPAN>Message Translator模式。而不应该兛_实体间结构{换的l节Q不同的数据模型之间的{换,比如ER模型不支持多对多关系而其他的支持q种Q。关于这个主题最老也使最相关的书?/SPAN>Kent的?/SPAN>Data and Reality》?/SPAN>
在前面的关键lg中我们提CMessages。当两个应用惌交换数据Q他们将数据包装在一?/SPAN>message中。但是一?/SPAN>Message Channel不能传输原始数据Q它只能传输包含在一?/SPAN>message中的数据Q即传输特定格式的数据)?/SPAN>
Message在消息系l中处于信息载体的位|,而在ESB中,q消息识别、序列以及生存周期等职责?/SPAN>
Message的结构涉及以下几个模式:
l Command Message
l Document Message
l Event Message
l Request-Reply
l Return Address
l Correlation Identifier
l Message Sequence
l Message Expiration
l Format Indicator
创徏和发送一?/SPAN>Message产生以下几个问题Q?/SPAN>
消息意图 Q?/SPAN> Message最l是Zq送一些数据,但是发送者可能有其他目的Q比如它希望接受者用消息做些事情。它可以发送一?/SPAN>Command MessageQ指定它希望调用的接受者上的函数或Ҏ(gu)。发送者告诉接受者运行那些代码。发送者可以发送一?/SPAN>Document Message来传送它的数据结构到接受者。发送者发送数据到接受者,但是不指定接受者应该做什么?/SPAN>
或者它可以发送一?/SPAN>Event MessageQ通知接受者发送者那里有一个改变。发送者不应告诉接受者应该怎样适应q个改变Q而只应提供通知?/SPAN>
q回一个应{?/SPAN> Q?/SPAN> 当一个应用发送一个消息,它通常期望得到一个回应来定消息被处理ƈ提供一个结果。这是一?/SPAN>Request-Reply场景?/SPAN>Request通常是一?/SPAN>Command MessageQ而应{是一个包含返回值或异常?/SPAN>Document Message。请求者应该在h中指定一?/SPAN>Return Address来告诉应{者用哪个通道来传回应{。请求者可能在一个处理过E中发送多个请求,所以应{应该包含一?/SPAN>Correlation Identifier来指个应{对应哪个请求?/SPAN>
有两?/SPAN>Request-Reply场景需要注意;它们都包含了一?/SPAN>Command Messageh和一个对应的Document Message应答。在W一个场景中Q?/SPAN>Message RPCQ请求不但要调用应答者的函数Q而且期望一个返回倹{这?/SPAN>RPC。另一个场景中Q?/SPAN>Message QueryQ请求者执行一个查询;应答者执行查询ƈ在应{中q回l果。这是远E查询?/SPAN>
大量的数?/SPAN> Q?/SPAN> 有时应用惌传送大量的数据l构Q放入一个单独的message里面不是很合适。在q种情况下,他们分解成可管理的消息块ƈ他们作?/SPAN>Message Sequence发送。这些消息必L序发送,以便接受者能够充_始数据结构?/SPAN>
慢速消?/SPAN> Q?/SPAN> 消息pȝ的一个问题是发送者通常不知道接受者要多久才能接受到消息。然而,消息的内容可能是旉敏感的,所以如果消息在某一旉内没有被接受Q它?yu)被忽略q取消。在q种情况下,sender应该使用Message Expiration来指定一个到期时间。如果消息系l在规定旉内无法传输一个消息,应该它取消q删除到Dead Letter Channel中。同L一?/SPAN>receiver接受C个超旉点的消息Q也要取消该消息?/SPAN>
MQ只选择使用消息是不够的。一个消息工作的其他军_性因素来自于消息所要完成的d?/SPAN>
在前面一个专题中Q我们列Z一?/SPAN>ESBpȝ所需要关心的所有方面的关键lgQ这里介l其中的Message Channels所x的问题及相关的模式?/SPAN>
Message Channel主题之下包含以下模式Q分别用于解?/SPAN>channel中不同方面的问题Q?/SPAN>
l Point-to-Point Channel
l Publish-Subscribe Channel
l Datatype Channel
l Invalid Message Channel
l Dead Letter Channel
l Guaranteed Delivery
l Channel Adapter
l Messaging Bridge
l Message Bus
当两个应用需要交换数据,它们通过q接两端?/SPAN>channel来发送数据。发送的应用可能不知道哪个应用将接受数据。然而,通过选择特定?/SPAN>channel来发送,发送者知道接受者将是守候在channel另一端等待数据的应用之一。通过q种方式Q生产数据的应用有了一个同数据消费者通讯的途径?/SPAN>
Message Channels面对的各个主要问题:
如果一个应用要传输或接受数据,它一定会用到一?/SPAN>channel。问题是你的应用要知道要使用什么样?/SPAN>channelQ以及用它来做什么?/SPAN>
固定?/SPAN>channel集合 Q?/SPAN> Channel中讨论的一个主题是Q一个应用可用的Message Channel集合一般是固定的。设计一个应用时Q一个开发者必ȝ道将某种cd的数据放到哪里可以同其他应用׃n该数据,以及从什么地方可以找到其他应用的特定数据。这些通讯路径不会在运行期动态的创徏和发玎ͼ它们需要在设计期间q定下来,以便应用知道它的数据从哪里来以及数据去哪里。( 虽然大多?/SPAN>channel必须被静态定义正确的,但是也有例外Q有些情况下动?/SPAN>channel是很好用的。一个例外就?/SPAN>Request-Reply模式中的reply channel。请求者可以创建或者获得一个应{者不知道的新?/SPAN>channelQƈ在请求消息中指定?/SPAN>channel?/SPAN>Return AddressQ应{者就可以使用它。另外一个例外是支持集成channels的消息系l实现。一个接受者可以订阅一个集成体pȝ?/SPAN>channelQ然后发送者可以发布消息到一个子channelQ而接受者不需要知道子channelQ仍然会收到消息。这些都是不常见的情况,channel通常仍然是在部v之前被定义,q且应用被设计连接到一个已知的channel集合 Q?/SPAN>
军_channel的集?/SPAN> Q?/SPAN> 一个相关的主题是,谁决定那?/SPAN>Message Channel是可用的 Q?/SPAN> messagepȝq是应用E序Q换句话_是由消息pȝ定一?/SPAN>channelQ然后要求应用程序用它们?q是应用军_它们需要什?/SPAN>channelQ然后要求消息系l提供它们?q个问题没有一个简单的{案Q设计必ȝchannel集合是P代的。首先,应用要决定消息系l提供哪?/SPAN>channel。然后应用将围绕q些channel设计它们的通讯Q但是如果这h不可行的Q它们将需要添加额外的channel。当一些应用已l用了一个确定的channel集合Q当加入新的应用Q它们将使用已存在的channel。当为应用添加新的功能,它们需要新?/SPAN>channel?/SPAN>
单向channel Q?/SPAN> 另外一个经常引h淆的是一?/SPAN>Message channel是单向的q是双向的。技术上来说Q两者都不是Q一?/SPAN>channel更像是一个桶Q一个应用放入数据,另外一个应用从中取出数据。但是由于数据是攑֜消息中从一个应用传到另一个,q?/SPAN>channelh方向性,使它变成单向的。如果一?/SPAN>channel是双向的Q应用将从中发送和接受数据Q虽然技术上是可行的Q但是会有小的问题Q应用将有可能持l的取出自己放进ȝ希望发送给其他应用的消息。所以,Z实践性的目的Q?/SPAN>channel是单向的?SPAN style="COLOR: red">作ؓl论Q两个应用如果有双向通讯Q它们需要两?/SPAN>channelQ每个方向一?/SPAN>?/SPAN>
如何使用Message channelsQ?/SPAN>
现在我们来讨Z下如何?/SPAN>channel?/SPAN>
一对一或者一对多 Q?/SPAN> 当你的应用共享一些数据,你希望只它׃nl一个应用还是对它感兴趣的所有应用?要传送数据到一个单独的应用Q?/SPAN>Point-to-Point Channel。这q不意味着发送到q个channel的每个数据都发送给同样的接受者,因ؓ一?/SPAN>channel可能有多个接受者。它意味着Q实际上Q保证每个数据都被同一个应用接收。如果你惌所有接收应用都能接收数据,使用Publish-Subscribe Channel。当你通过q种方式发送数据,channel高效的复制数据到每一个接收者?/SPAN>
什么类型的数据 Q?/SPAN> M内存中的数据都有一个类型。另一斚wQ所有数据都是一?/SPAN>bytes集合。消息系l工作同q类|消息内容必须W合某些cd以便接受者了解数据的l构?/SPAN>Datatype Channel认ؓ在一?/SPAN>channel中的数据必须拥有同样的类型?SPAN style="COLOR: red">q也是ؓ什么消息系l需要很?/SPAN>channel的主要原?/SPAN>Q每?/SPAN>channel一U格式)。如果数据可以是L的格式,那么消息pȝ在两个应用之间只需要两?/SPAN>channel?/SPAN>
无效的和q期的消?/SPAN> Q?/SPAN> 消息pȝ可以定消息被正的传输Q但是它不能保证接受者知道如何处理它。接收者对数据格式和意义存在期望。当它接收到一个不W合期望的消息,它什么也不能做。它们能作的Q就是将q个陌生的消息放入到一个特别设计的Invalid Message Channelq希望某些监控这?/SPAN>channel的工兯够取个消息,q指如何处置它们。许多消息系l有一个类似的内徏特征Q一?/SPAN>Dead Letter ChannelQ用来存放成功送出但却无法成功投递的消息。另外,一个系l管理工具应该监?/SPAN>Dead Letter Channelq且军_如何处置q些无法投递的消息?/SPAN>
故障?/SPAN> Q?/SPAN> 如果一个消息系l发生故障或停机l护Q它的消息会怎样Q当它重启ƈ重新q行Q它的消息能否还在它?/SPAN>channel中?默认的:不会Q?/SPAN>channel消息存储在内存中。然而,Guaranteed Delivery?/SPAN>channel持久化以便将它们的消息存储到盘上。这会媄响效率,但会使消息更加可靠,即消息pȝ是不可靠的?/SPAN>
非消息客L Q?/SPAN> 如果一个应用不能连接到一个消息系l但是仍然想要参与消息怎么办?通常它只能自认倒霉了,但是如果消息pȝ可以通过某种方式q接到应用系l?/SPAN> Q?/SPAN> 通过它的用户界面Q它?/SPAN>service APIQ它的数据库Q或者一?/SPAN>TCP/IP?/SPAN>HTTPq样的网l连?/SPAN> Q?/SPAN> 那么消息pȝ可以使用一?/SPAN>Channel Adapter。这允许你连接到一个或多个q接到应用的channel而不必改变应用或者可能也不需要一个同应用q行在同一个机器上的消息客L。有时‘非消息客户端’真的是一个消息客LQ但是只有连接的是其他消息系l的时候?/SPAN>
通讯中枢 Q?/SPAN> 随着来多的企业应用系l连接到消息pȝ以便通过消息暴露他们的功能,消息pȝ变成了企业中一站式功能的集散地。一个应用只需单的知道用哪?/SPAN>channel来请求功能,以及从哪个监听结果。消息系l本质上变成一个消息ȝQ一个提供所有企业应用甚臛_化中的应用和功能的中枢。你可以更快速的集成?/SPAN>
如你所见,使用消息构徏应用不仅仅是他们连接到消息pȝq发送消息。消息必M?/SPAN>Message Channel来发送?/SPAN>Channel必须被设计ؓ某个目的服务Q比如基于被׃n的数据类型,׃n数据的应用类型,和接收数据的应用?/SPAN>
企业集成有很多种模式Q随着技术的发展Q实时的、面向消息的企业集成来成Z,面向消息的企业集成的E_性和兼容性要求其基础Ӟ也就?/SPAN>messagepȝ必须提供_强壮和可扩展的设计,下面几种是作为面向消息的企业集成的基件所必须提供的几个关键性组件?/SPAN>
消息集成使得messagepȝ负责转换两个应用之间的数据格式,从而得应用可以专注于他们需要共享什么数据而不是如何共享它们?/SPAN>
Channels ?Messaging应用通过一?/SPAN>Message Channel传送数据,一?/SPAN>sender?/SPAN>receiver的虚拟管道。一个新安装的消息系l默认不包含MchannelQ你必须知道你的应用需要怎样通讯Q然后才能徏?/SPAN>channel来完成它?/SPAN>
Messages ?Message是在channel上传输的不可分割的包。因此,Z传输数据Q应用必d数据打包成一个或多个packetsQ将每个packet包装成一?/SPAN>messageQ然后将其传输到一?/SPAN>channel。同LQ一?/SPAN>receiver应用在接受到message后必Mmessage中提取出数据才能使用?/SPAN>Messagepȝ应该能重复的传输messageQ直到它成功为止?/SPAN>
Pipes and Filters ?最单的情况下,messagepȝ一个消息直接从sender计算Z送到receiver计算机。然而,通常在消息从sender中发出后Q?/SPAN>receiver接受C前,有一些动作需要对message执行。D例来_message也许需要验证或者{换?/SPAN>Pipes and Filters架构使用channel多个处理步骤连接v来?/SPAN>
Routing ?在一个大型的、拥有许多不同的应用?/SPAN>channelq接的企业应用中Q一?/SPAN>message可能需要穿q多?/SPAN>channel才能到达最l目的地?/SPAN>Message的\由如此复杂以至于最初的发送者无法知道那?/SPAN>channel能将message传送给最l的receiver。因此,最初的发送者将message发送给一?/SPAN>Message RouterQ一个以Pipes and Filters架构中的filter形式存在的应用组件?/SPAN>Router决定如何将message发送到最l?/SPAN>receiver或者至是下一?/SPAN>Router?/SPAN>
Transformation ?不同的应用的数据格式可能不同。ؓ了调?/SPAN>sender?/SPAN>receiver之间的数据格式不同的问题Q?/SPAN>message必须l过一个中介的filterQ一?/SPAN>Message TranslatorQ它?yu)?/SPAN>message从一个格式{换成另外一个格式,或{换成一个公q格式?/SPAN>
Endpoints ?大多数的应用E序没有内徏的能力来同一?/SPAN>messagepȝ交互。因此他们必d含一个中间层Q它知道应用pȝ如何工作Q也知道messagepȝ如何工作Qƈ桥接两个pȝ。这个系l是一lƈ列的Message EndpointsQ它能够使得应用发送和接受message?/SPAN>
System manager Q?/SPAN> 作ؓ一个大型的消息集成pȝQ其面向消息的、异步、低耦合的本质得系l更加难以调试,q行期的状态也难以跟踪Q所以,我们必须有强有力的手D进行系l的q行期管理和监控Q同时最好能够在q行q行动态更斎ͼ以保障系l的强壮性?BR>
企业应用集成是一个巨大而复杂的pȝQ作为其基础件ESBpȝQ必能够提供对其完全的支撑以及_强壮的系l,q正是ESBpȝ的难度所在?/SPAN>
不可以用普通的dispatcherResult?/SPAN>response?/SPAN>outputStream中写入东西,否则覆盖所有的dispatcher?/SPAN>jsp面
?/SPAN>xwork.xml中配|?/SPAN>result-typeQ?/SPAN>
<result-types>
<result-type name="image"
class="com.bnt.afp.action.verify.ImageResult"/>
</result-types>
d一个生成图片的actionQ?/SPAN>
<action name="imageAction"
class="com.bnt.afp.action.verify.ImageAction">
<result name="success" type="image"/>
</action>
在需要生成验证图片的地方q样调用Q?/SPAN>
<img border=0 src="imageAction.action">
ImageAction里只要简单的q回SUCCESS可以了
VerifyImage
写了几个月的通讯中间Ӟ再次带领一个J2EE目Q用WebWork、Spring、HibernateQ感觉写J2EE目像在休假,要考虑的事情少之又,无论是效率、异常处理、线E调度、架构模式,一切都不再那么重要Q无需考虑那么多,只要语义清晰Q沟通流畅就好了?BR>惌v一周前跟Jerry聊天Q说起因为Unixware下JDK1.3的notify语义的不E_问题而一天内重新~写了三ơ通讯框架Q最后采用了完全非框架的q程化写法,Jerry说应该先写出一个实玎ͼ然后在之上重构,像爬山一P不可能一下子攀d峰Q当时虽然心里感觉不是这P但竟一时语塞,不知从何说vQ再ơ回到J2EE开发,才恍然明白那天的感觉Q框架开发和业务开发的不同在于,很难重构Q尤其是通讯框架Q架构通常军_了它的几个重要指标?/P>
架构模式不同于设计模式,设计模式的问题可以通过重构解决Q而架构模式几乎只能重新做Q当然也有例外)Q架构一旦确定,很多东西无法再加入Q所以ؓ什么很多开源的J2EE框架在大版本升后不得不抛弃向后兼容。这也是Z么国产通讯框架Cindy的作者想在其中加入FilterChainQ而最l放弃的原因Q因对基库的改动实在太大?/P>
而MINA的架构就_灉|Q它屏蔽了不同通讯方式和通讯底层事g机制的差异,像在如同Cindy和Netty2q种ZNIO的reactor模式之上的框Ӟ要想重构到BIOQ就几乎要全部重写,不过Netty2要好一些,毕竟有Netty1作ؓ铺垫Q所以在NIO的reactor的\上走的不是很q(NIO的reactor实现真是的不咋个Q,而MINA则只需要在SocketIoProcessor中用Helf Sync/Helf Async模式替换掉reactor之上的事件处理即可,当然Q最好还要提供线E池以便q行overload shieldQ在向Apache LDAP团队提交了MINA的JDK1.3核心库时也曾x赯问题Q可惜后太忙Q忘C。不q我想以Trustin的聪明,一定会惛_q个问题?/P>
l OpenҎ(gu)
a) ?/SPAN>script中引用的包含java对象?/SPAN>class文g?/SPAN>jar文gQ必d含在<ECLIPSE_INSTALL>\plugins\org.eclipse.birt.report.viewer\birt\WEB-INF\lib.目录?/SPAN>
b) 引入一?/SPAN>packageQ?/SPAN>importPackage(Packages.com.yourCompany.yourApplication); 引入通常?/SPAN>openҎ(gu)的第一行?/SPAN>
c) 创徏一?/SPAN>java对象的实例:var myList = MyListFactory.getList();
d) ?/SPAN>java对象中获取数据的典型方式是从该对象中获得一个包含数据的IteratorQ?/SPAN>
var iterator = myList.getIterator();
l FatchҎ(gu)Q?/SPAN>fatchҎ(gu)?/SPAN>Open中创建的java实例中获得数据,q赋值给行)
a) FatchҎ(gu)的第一步是判断Iterator中是否有数据Q?/SPAN>
if(iterator.hasNext() == false ){
return null;
}
b) 然后是从iterator中得C个行对象node以便得到该行中每列的数据Q?/SPAN>
var node = iterator.next( );
row[1] = node.getFirstCol( );
row[2] = node.getSecondCol( );
row[3] = node.getThirdCol( );
c) 最后,是返?/SPAN>trueQ?/SPAN>return true;
l CloseҎ(gu)Q?/SPAN>
a) 最后,?/SPAN>CloseҎ(gu)中清理所有创建的对象Q?/SPAN>
myList = null;
iterator = null;
node = null;
l ReportEngine的构造函数要传入一?/SPAN>EngineConfig作ؓ参数Q如果参CؓnullQ则一个默认值的ReportEngine被创建?/SPAN>
l 退出时Q应用应该调?/SPAN>destroy()来卸载外挂以及删除时文?/SPAN>
l 使用report engine有以下几个主要步骤:
a) 创徏一?/SPAN>EngineConfig来设|?/SPAN>report engine的选项
b) 创徏一?/SPAN>ReportEnginecȝ实例
c) 你可以用q个对象去进行多UQ?/SPAN>
d) 使用ReportEngine的一?/SPAN>openReport( )Ҏ(gu)来打开一?/SPAN>report design文g
e) 使用IgetParameterDefinitionTask来获?/SPAN>report参数的信?/SPAN>
f) 使用IrunAndRenderReportTaskq行q{换一?/SPAN>reportC个输出格?/SPAN>
g) 调用你的report engine?/SPAN>destroy( )Ҏ(gu)
l EngineConfigQ?/SPAN>The EngineConfig class wraps configuration settings for a report engine. It allows a developer to specify where to look for engine plug-ins and data drivers, and to add an application-wide scriptable object.
l IReportRunnableQؓ了?/SPAN>report engineQ你必须首先调用openDesign( )Ҏ(gu)来打开report设计文gQ这些方法返回一?/SPAN>IreportRunnable实例来代?/SPAN>report设计文g?/SPAN>engine’s view。?/SPAN>IreportRunnable做以下Q务:
a) Get parameter data
d) Get images embedded within the report design
l IEngineTaskQ该cL供一个管理脚本上下文以及report locales的框Ӟ它从ReportEngine的工厂方法中创徏Q需要参敎ͼIreportRunnable对象?/SPAN>a scripting context, and a locale?/SPAN>
a) org.eclipse.birt.report.model.apiQ这个包内包含了93?/SPAN>classQ两个接口和一?/SPAN>exceptionQ这个包是ؓ那些惌定制report designer的开发者用的
b) org.eclipse.birt.report.engine.apiQ?/SPAN>q个包包含了一个类Q?/SPAN>17个接口和四个exceptionQ是l那些想要定制一?/SPAN>report generator的开发者用的
c) org.eclipse.birt.chart hierarchyQ这个包是给惛_制一?/SPAN>chart generator的开发者用的
l BIRT report engine在几个环境提供了报表生成和翻译服务,包含以下lgQ?/SPAN>
a) Stand-alone engineQ这?/SPAN>engine可以让开发者用一个命令行E序来从一?/SPAN>report design文g(.rptdesign)中得?/SPAN>Html?/SPAN>PDF格式?/SPAN>report
b) BIRT report viewerQ?/SPAN>BIRT Report Designer使用它来预览report。这个程序是一?/SPAN>webE序Q它q行在一?/SPAN>Eclipse内嵌?/SPAN>Tomcat中,q个Tomcat中有一个内嵌的report engine
c) Custom report designer with an embedded engineQ一个定制的桌面报表应用集成BIRT report engine来预览报?/SPAN>
d) Web application that embeds the engineQ一个类gBIRT report viewer?/SPAN>WebE序Q可以生基?/SPAN>web的报表?/SPAN>
l Report engine的核?/SPAN>engineq行q实施报表,而将其他的环境相关的d留给q行该引擎的应用E序Q比如:URL construction, image storage, and design file caching
l BIRT report engine?/SPAN>API可以做以下几件事情:
a) 发现一lؓ报表定义的参?/SPAN>
b) 获得参数的默认?/SPAN>
c) q行报表产生HTML?/SPAN>PDF格式的输?/SPAN>
d) 为报表生图片或chart
a) 在查询时指定qoQ以便在数据库或其他数据源中qo数据Q要量使用q种方式来过滤数据,可以通过两种方式来指?/SPAN>SQL SELECT声明Q?/SPAN>
1. 在设计期间的SQL Select中以WHERE的方式指定,q在数据库中执行?/SPAN>
2. 创徏report参数来让用户指定Q在SQL SELECT?/SPAN>WHERE处用参数来指定条gQ用这U方式,WHERE的参数在q行期指定,q在数据库中执行?/SPAN>
b) ?/SPAN>BIRT Report Designer中过滤数据,使用javascript或者数据不是在一个数据库中从而不能执?/SPAN>SQL语句的情况下Q可以用以下两种方式来执行这U过滤:
1. ~辑数据集来指定filterQ用这U技术,查询获得你的SELECTzd的全部数据,然后BIRT Report Designerqo数据以便获得W合你指定的条g的数据,׃数据集只能有一个,所以这U技术只能用一U?/SPAN>table或者所有的report都显C相同的?/SPAN>
2. ~辑report element filter properties来指定要昄的行Q用这U技术,BIRT Report Designer处理q个q程Q如果有多个table?/SPAN>list?/SPAN>chart使用同一个数据集Q而且要显CZ同的行,则就需要用这U技?/SPAN>
但是作ؓ技术h员,我们要拨开SOA的华丽外,看看它到底是什么?BR>
SOA的演变过E:
web Service-->以CorbaZ表的DOC-->Zlg服务器的N-Tier-->Zweb服务器的T-Tier-->C/Sl构
其根本的通讯方式Q几q来未曾变化Q只不过是多I了几g马甲而已Q从技术角度讲Q如果对|络中间件的架构熟?zhn)的话Q从最底层的TCP/IP通讯开始自己构Z个webService的实Cq什么难事,作ؓ技术h员,我更惛_注一些目前可以带来实际好处的技术,如:AOP/脚本语言/IF/微内核的体系l构Q甚x镜花水月的MDA
但是Q如前面所说这是从技术的角度来看待SOA的发展,而实际上Q每一ơ穿上新的马Ԍ都得应用的基础架构更进一步接q业务,所以,看待SOA也不能仅仅从技术的角度Q从整个企业的架构来考虑Q虽然不太愿意接受大厂商的SOA宣传的轮番蘪炸(它们l常aq其实)Q但是我仍然不得不说SOA的思想和发展思\实不错。有Z试试看,也许真的很不错?/P>