模块化Java:声明式模块化
本文是模块化Java系列文章的第4篇,介绍的是声明式模块化。文中描述了组件如何以声明的方式来定义并组织在一起,而无需让代码依赖于OSGI API。

作者 Andrew Kuklewicz 译者 罗小平 发布于 2007年5月4日 下午8时54分
Rails已在数据库驱动型Web应用领域站稳脚跟。而集成了消息处理的插件式框架——ActiveMessaging,更扩大了Rails的应用范围。利用ActiveMessaging和Rails,我们可以轻松集成全异系统(如MQ消息发送模块、J2EE Web应用和后台常驻任务等),或创建事件和消息驱动型架构。有人这样总结过:ActiveMessaging就像ActiveRecord为数据库所做的一切那样,正为消息处理而努力。本文将介绍ActiveMessaging、与其相关的技术,以及在Rails中的使用方法。
实现消息处理,首先需要三个方面的支持:通讯协议、协议服务端代理、协议客户端库。从技术角度而言,剩下的工作就是开发一个实现消息发送和接收的系统了。在本文的例子中,我们将把服务端和客户端合二为一,放在同一个程序中。ActiveMessaging支持Stomp协议。这是一个通过无线连接,使用TCP/IP,实现文本型消息流式传输的协议标准。其设计理念要求尽可能将协议简化,以求无论利用哪种语言开发客户端或服务端,都能相当轻松(比如Ruby Stomp客户端代码,连带注释和空行,总行数仅约400)。因此,它几乎可以集成任何系统。
Apache ActiveMQ消息代理缺省支持Stomp,当然也可以使用其他代理,而且选择是越来越多。比如最近公布的StompConnect项目,计划向绝大多数开源消息处理类产品开放Stomp和ActiveMessaging,并实现任何JMS代理到Stomp代理的转换。在客户端,ActiveMessaging支持基于适配器模式(Adapter Pattern)的协议,就Stomp而言,它使用在Stomp RubyGem基础上扩展而成的适配器。未来可能支持的适配器更多,但目前只有Stomp。
本文中,我们使用还未正式发布的ActiveMQ4.2代理。ActiveMQ在所有平台上都有安装说明;如果你有Java1.4或更高版本,那么可以简化安装过程:
cd /usr/local/src
#unix and cygwin
wget http://people.apache.org/repo/m2-snapshot-repository/org/apache/activemq/apache-activemq/4.2-SNAPSHOT/apache-activemq-4.2-20070221.081507-10-src.tar.gz
#os x
curl -O http://people.apache.org/repo/m2-snapshot-repository/org/apache/activemq/apache-activemq/4.2-SNAPSHOT/apache-activemq-4.2-20070221.081507-10-src.tar.gz
cd ..
tar xvfz apache-activemq-4.2-20070221.081507-10-src.tar.gz
cd apache-activemq-4.2-incubator-SNAPSHOT
./bin/activemq
这就OK了!缺省情况下,ActiveMQ对Stomp的支持会自动配置完成;若自动配置不成功,你可以在conf/activemq.xml中添加如下设置:
<transportConnectors>
...
<!-- Add this line -->
<transportConnector name="stomp" uri="stomp://localhost:61613"/>
</transportConnectors>
以上是ActiveMQ所需的最小化配置。更详细的情况可以参考ActiveMessaging的ActiveMQ维客,以及ActiveMQ用户手册。
Rails 1.1和MySql准备就绪后,还需要安装两个工具:daemons 和Stomp:
sudo gem install daemons
sudo gem install stomp
现在让我们新建一个Rails工程“MessageMonster”以及对应数据库,最后安装ActiveMessaging插件。
cd /usr/local/dev
rails MessageMonster
mysqladmin create messagemonster_development -u root
cd MessageMonster
script/plugin install http://activemessaging.googlecode.com/svn/trunk/plugins/activemessaging
所有准备工作就绪,现在可以写程序了。
首先需要创建“处理器”,用ActiveMessaging的术语来说,就是一个支持消息目标者有序接收和处理消息的类。它在设计模型中是必不可少,相当于消息驱动的控制器,代码量也占最大比例。
如你所愿,处理器可以自动生成:
script/generate processor PersistMessage
第一次运行“generate”,会输出如下结果:
create app/processors
create app/processors/persist_message_processor.rb
create config/messaging.rb
create config/broker.yml
create app/processors/application.rb
create script/poller
首先考察broker.yml,注意各项参数,确保代理配置正确:
development:
adapter: stomp
login: ""
passcode: ""
host: localhost
port: 61613
reliable: true
reconnectDelay: 5
...
以上只包括了ActiveMQ的缺省配置项。如果是正式发布的产品,远程运行代理,则还需要增加访问用户和密码项。
接下来再看看persist_message_processor.rb:
class PersistMessageProcessor < ApplicationProcessor
subscribes_to :persist_message
def on_message(message)
logger.debug "PersistMessageProcessor received: " + message
end
end
上述代码实现了:persist_message消息的订阅,并指定了方法on_message。当:persist_message消息到来时,ActiveMessaging将回调on_message。参数message负责按字符串格式传递消息内容;依靠@message,还可以直接访问Stomp消息对象。通过再次调用subscribes_to,处理器可以订阅更多消息。
:persist_message是处理器订阅的目标消息的逻辑名。在config/messaging.rb中定义目标消息:
ActiveMessaging::Gateway.define do |s|
s.queue :persist_message, '/queue/PersistMessage'
end
messaging.rb类似于Rails中的routes.rb。它主要实现逻辑名(:persist_message)到代理(/queue/PersistMessage)中目标消息的映射。当然还有很多其他配置项,但就本例而言,自动生成的缺省配置已经足够了。
接下来,我们要告知处理器预先存储消息以供处理,如下创建一个消息模型:
script/generate model message
现在,用如下两行代码更新db/migrate/001_create_messages.rb:
create_table :messages do |t|
t.column :body, :text
t.column :received_date, :datetime
end
调用migrate创建该数据表:
rake db:migrate
接下来修改处理器的on_message方法,这将使用到新的消息模型:
def on_message(message)
logger.debug "PersistMessageProcessor received: " + message
my_message = Message.create(:body=>message, :received_date=>DateTime.new)
end
看到这里,我们仔细想想会发现,其实没有什么新东西,和在Rails控制器中编码完成相同功能的过程差不多。因此使用ActiveMessaging时,Rails应用环境的所有便利性都可供利用。
处理器一旦捕获消息,就可将它抛出(像瓶装后逐个抛售那样)等待处理。
发送消息时,我们会在同一个应用程序中用到Rails视图和控制器:
script/generate controller SendMessage index
编辑视图,提交消息文本,显示预先持久化的消息的可更新列表:
style="color: green">
Send Message >Message
编辑控制器,发送消息。ActiveMessaging包含一个提供消息简单发布方法的小型类MessageSender,利用它可从任何类轻松实现消息发送。publishes_to定义了消息接收者,但除了验证config/messaging.rb中所配置目标者的有效性,不干别的事。如下是控制器使用这些方法的过程:
require 'activemessaging/processor'
class SendMessageController < ApplicationController
include ActiveMessaging::MessageSender
publishes_to :persist_message
def index
@messages = Message.find :all
end
def new
@message = params[:message]
publish :persist_message, @message
flash[:notice] = "'#{@message}' sent"
@messages = Message.find :all
render :action => 'index'
end
end
至此,大功告成。控制器将在用户提交时发出消息,当你下次浏览或者刷新此页面时,将看到被处理器保存的消息。
ActiveMessaging在独立进程中运行,由script/poller控制。因此仅仅启动Rails服务器,是无法接收到消息的。运行这个例子,我们总共需要启动三个进程:ActiveMQ代理、Rails服务器(发送消息)和script/poller(接收消息)——每个进程都是系统的独立节点。
启动ActiveMQ:
cd /usr/local/apache-activemq-4.2-incubator-SNAPSHOT
./bin/activemq
启动Rails:
cd /usr/local/dev/MessageMonster
script/server
启动ActiveMessaging:
cd /usr/local/dev/MessageMonster
script/poller run
script/poller遵循后台程序的运行规则。处理让进程保持运转的“run”参数外,还可以传递“start”、“stop”、“restart”和“status”。另外,为提高消息处理效率,也能同时运行多个进程实例。
现在,打开测试页面(如http://localhost:3000/send_message),输入消息吧,比如经典的“Hello World”。消息送达时,你应该在poller窗口看到如下信息:
Loading /usr/local/dev/MessageMonster/app/processors/application.rb
Loading /usr/local/dev/MessageMonster/app/processors/persist_message_processor.rb
=> Subscribing to /queue/PersistMessage (processed by PersistMessageProcessor)
=> All subscribed, now polling
PersistMessageProcessor received: Hello World
poller总会显示启动时加载的处理器,以及代理上的订阅请求。如果代理不可用或不存在,系统会根据broker.yml的配置尝试别的代理。另外,你还能在poller中看到ActiveMessaging处理器接收的、来自于Rails的消息。而且,如果你使用“Refresh List”功能,将会在Rails视图中看到被ActiveMessaging处理器持久化的消息。
希望你能喜欢这篇介绍ActiveMessaging的文章,相信你已经感觉到了它的潜力和易用性。其实,ActiveMessaging还有很多本文没有提及的高级功能,如优化的异常处理、多poller运行群组处理器,以及异步消息中Stomp和ActiveMQ消息头的处理方法、JMS集成和可选订阅等。是不是相当惊讶呢,现在不会认为ActiveMessaging无法满足你的需要了吧!
译者简介:罗小平,上海某大型公司互联网中心技术总监,CSDN大版主,网络ID为lxpbuaa(桂枝香在故国晚秋),曾著有《Delphi精要》一书。个人博客为http://blog.csdn.net/lxpbuaa,现在CSDN主持翻译国外专家Herb Sutter的中文博客。他的Email和MSN为lxpbuaa AT 263.net。
本采访是在伦敦举行的QCon2009上记录的,Ian Robinson和Jim Webber探讨了如何将Web作为整合平台以及REST在理论上和实践中的好处。
项目管理对于项目成败至关重要,但实践中每个项目都有自己的独特性,没有现成的解决方案可以套用。书中从应对实际风险的角度出发,讲述了从项目启动、项目规划到项目结束的整个管理流程,展示了作者的思考过程。本迷你书从原书中精选出5个章节。
在这个演讲中,Fred将会揭示敏捷的一些外在因素,并会重点关注敏捷获得成功的内在原因。从案例研究和真实的项目经验来看,Fred认为:工具、管理体系都不能让你变得敏捷。敏捷的成功,植根于士气高涨、充分授权的工作者身上,他们能够以不同以往的方式思考问题。
Eben Hewitt的新书《Java SOA Cookbook》从Java实现的角度讨论了面向服务架构。Eben在书中讨论了SOA基础、工具、最佳实践和SOA治理等主题。
Mark Richards的新书《Java消息服务》第二版覆盖了JMS的许多主题, 包括发布和订阅模式以及点对点模式,消息过滤和事务等。InfoQ与Mark谈论了跟他的新作。
2 条回复
关注此讨论 回复