Apache Tomcat是可论证的当今使用最广的可用的Java web容器。在全世界Tomcat被用作开发和产品因为它极度robust,高度configurable,并且有一定数量的公司进行商业化支持。因为它的广泛使用,Tomcat提供了为集成第三方资源,例如JDBC数据源,JMS连接工厂等等和使它们的JNDI可用的facilities。在该章节中,我们将向你显示如何集成ActiveMQ到Apache Tomcat。你将需要下载Apache Tomcat 6.0.26( http://mng.bz/75qc)并将它解压到你的电脑上。
Tomcat为JNDI资源提供两种风格的配置:local JNDI context和global JNDI context。配置一个local JNDI资源意味着资源仅对部署到Tomcat特定的web application有效。在global JNDI context中配置资源意味着资源在部署到Tomcat的任意网络应用有效。不同类型的JNDI风格配置是不同的,所以让我们都看一看。
注意
local JNDI配置示例和global JNDI配置示例无法同时部署。因为这会导致classloader issues并使ActiveMQ无法正确部署。确保某刻只部署某一个风格的配置。
8.2.1使用local JNDI在Tomcat中集成ActiveMQ
在资源定义的地方,local JNDI配置限制了应用对资源的可用性。以这种风格配置的tomcat,JNDI资源在名为META-INF/context.xml的文件中定义。下面的列表显示了context.xml文件:
Listing 8.5 The Tomcat context.xml file
<Context reloadable="true">
<Resource auth="Container"
name="jms/ConnectionFactory"
type="org.apache.activemq.ActiveMQConnectionFactory"
description="JMS Connection Factory"
factory="org.apache.activemq.jndi.JNDIReferenceFactory"
brokerURL="vm://localhost?brokerConfig=xbean:activemq.xml"
brokerName="MyActiveMQBroker"/>
<Resource auth="Container"
name="jms/FooQueue"
type="org.apache.activemq.command.ActiveMQQueue"
description="JMS queue"
factory="org.apache.activemq.jndi.JNDIReferenceFactory"
physicalName="FOO.QUEUE"/>
</Context>
清单8.5是特定于Tomcat的。第一个元素命名为jms/ConnectionFactory--它定义了一个ActionMQ连接工厂并利用ActiveMQ中的优点,通过连接工厂启动一个代理实例。第二个元素名为jms/FooQueue在ActiveMQ中定义了一个JMS queue。这个配置文件live with web application并被tomcat自动获取来配置资源。Tomcat使得他们可以通过一个标准的JNDI查找示例web应用程序。
注意
$TOMCAT_HOME变量一般被用来指向Tomcat安装目录,它并不是必须在你的环境中设置的
为了测试local JNDI资源,使用下面的步骤:
第一步 复制jms-webapp-local/target/jms-webapp.war文件到$TOMCAT_HOME/webapps目录中。
第二步 启动Tomcat:
$ cd $TOMCAT_HOME
$ ./bin/catalina.sh run
Using CATALINA_BASE: /opt/apache-tomcat-6.0.26
Using CATALINA_HOME: /opt/apache-tomcat-6.0.26
Using CATALINA_TMPDIR: /opt/apache-tomcat-6.0.26/temp
Using JRE_HOME:
/System/Library/Frameworks/JavaVM.framework/Versions/
CurrentJDK/Home
Using CLASSPATH: /opt/apache-tomcat-6.0.26/bin/bootstrap.jar
...
INFO - BrokerService - ActiveMQ 5.4.1 JMS Message
Broker (FooBroker) is starting
...
Apr 8, 2010 9:03:03 PM org.apache.catalina.startup.Catalina start
INFO: Server startup in 3542 ms
你能在输出中看到ActiveMQ实际行使用了activemq.xml配置文件因为brokerName FooBroker被使用了。发送run属性到catalina.sh脚本将使Tomcat运行这样它的输出会出现在控制台上。如前面提到的能看到输出的能力是有用的,并也将帮助你在几步内验证收到的消息。
如在本章开头所提到的,该配置利用了ActiveMQ中独特的特性。该特性允许ActiveMQ代理通过建立一个连接工程简单地启动将它传递到一个代理URI。这个连接工厂尝试去连接URI所指的代理,并且如果没有一个存在,则它将启动一个。如你所能看到的,这是个ActiveMQ中handy特性。
第三步 访问[uri]http://localhost:8080/jmswebapp[/uri]并使用网页发送一个消息。图8.4是你应该能看到的示例。
第四步 修改发送的消息,在控制台确认consumer接收到消息。看下下面的输出:
...
INFO: Server startup in 3306 ms
INFO - SingleConnectionFactory - Established shared
JMS Connection:
ActiveMQConnection {id=ID:mongoose.local-55759-1270249165283-2:1,
clientId=null,
started=false}
INFO - JmsMessageDelegate - Consumed message with payload:
This is a test message
注意控制台的输出--特别是,最后一行是一个从JmsMessageDelegate bean输出的日志消息。该行表明消息已经被consumed,并且你看到消息的正文被打印出来。
本地配置的ActiveMQ资源是一个很好的方法,因为这些资源包含于web应用程序。在Tomcat它内部没有什么需要修改或配置,这不同于资源配置为全局JNDI的方式。
8.2.2使用global JNDI在Tomcat中集成ActiveMQ
在Tomcat中的global JNDI配置也很容易使用。它仅需要一点额外的配置和复制一些JARs到Tomcat lib目录。global JNDI的优点是资源对部署到Tomcat的任何web application是可用的。在该风格的配置中,JNDI资源定义于Tomcat 应用服务中的名为conf/server.xml和conf/context.xml配置文件中。下面的列表展示了server.xml文件的相关部分。
Listing 8.6 The Tomcat server.xml file
<GlobalNamingResources>
...
<Resource auth="Container"
name="jms/ConnectionFactory"
type="org.apache.activemq.ActiveMQConnectionFactory"
description="JMS Connection Factory"
factory="org.apache.activemq.jndi.JNDIReferenceFactory"
brokerURL="vm://localhost?brokerConfig=xbean:conf/activemq.xml"
brokerName="MyActiveMQBroker"/>
<Resource auth="Container"
name="jms/FooQueue"
type="org.apache.activemq.command.ActiveMQQueue"
description="A sample queue"
factory="org.apache.activemq.jndi.JNDIReferenceFactory"
physicalName="FOO.QUEUE"/>
...
</GlobalNamingResources>
显示在表8.6中的server.xml文件的<Resource>元素在Tomcat中注册了JNDIReferenceFactory对象来建立提到的对象类型--ActiveMQConnectionFactory和ActiveMQQueue。再一次,ActiveMQ is unique in the fact that a full broker instance can be created by creating an ActiveMQConnectionFactory。brokerURL属性被用来传递代理URI,它允许使用任何被支持的transports(TCP,VM等等)。它也支持可选的brokerConfig属性为启动的ActiveMQ实例用于指向一个配置文件。
下面要修改的文件是context.xml文件;如下显示相关添加的内容。
Listing 8.7 The Tomcat context.xml file
<Context>
...
<ResourceLink global="jms/ConnectionFactory" name="jms/ConnectionFactory" />
<ResourceLink global="jms/FooQueue" name="jms/FooQueue" />
...
</Context>
<ResourceLink>元素定义了一个到定义在global的JNDI context的资源的链接并在Tomcat实例中expose这些资源到发布的所有的web application。
为了测试global JNDI资源配置,使用下面的步骤:
第一步 复制下面的JARs到$TOMCAT_HOME/lib目录:
■ activemq-all-5.4.1.jar
■ spring-beans-2.5.6.jar
■ aopalliance-1.0.jar
■ spring-context-2.5.6.jar
■ commons-logging-1.1.1.jar
■ spring-context-support-2.5.6.jar
■ geronimo-j2ee-management_1.0_spec-1.0.jar
■ spring-core-2.5.6.jar
■ geronimo-jms_1.1_spec-1.1.1.jar
■ spring-jms-2.5.6.jar
■ geronimo-jta_1.0.1B_spec-1.1.1.jar
■ spring-tx-2.5.6.jar
■ log4j-1.2.14.jar
■ spring-web-2.5.6.jar
■ org.osgi.core-4.1.0.jar
■ spring-webmvc-2.5.6.jar
■ spring-aop-2.5.6.jar
获取这些JARs的最容易的地方是在用于local JNDI配置的jms-webapp-local项目建立之后从那个项目里。在运行Maven命令编译jms-webapp-local项目的命令之后,在jms-webapp-local/target/jms-webapp/WEB-INF/lib/目录找一下这些JARs。简单地从那个目录复制JARs到$TOMCAT_HOME/lib目录。
第二步 如提到的在配置中做些修改,它们必须被包含在WAR文件中。为了建立jms-webapp-global项目并建立一个新的WAR文件,从命令行,运行下面的Maven命令:
$ cd jms-webapp-global
$ mvn clean install
...
[INFO] Scanning for projects...
[INFO] ---------------------------------------------------------------
-----
[INFO] Building jms-webapp-global
[INFO] task-segment: [clean, install]
[INFO] ---------------------------------------------------------------
-----
...
[INFO] ---------------------------------------------------------------
-----
[INFO] BUILD SUCCESSFUL
[INFO] ---------------------------------------------------------------
-----
...
运行这个命令之后,一个WAR文件将出现在target文件夹下。
第三步 复制jms-webapp-global/activemq.xml文件到$TOMCAT_HOME/conf/activemq.xml中。这使ActiveMQ配置文件在classpath上可用。
第四步 复制jms-webapp-global/target/jms-webapp.war到$TOMCAT_HOME/webapps目录。这将部署示例web应用。
第五步 使用下面的命令启动Tomcat:
$ cd $TOMCAT_HOME
$ ./bin/catalina.sh run
Using CATALINA_BASE: /opt/apache-tomcat-6.0.26
Using CATALINA_HOME: /opt/apache-tomcat-6.0.26
Using CATALINA_TMPDIR: /opt/apache-tomcat-6.0.26/temp
Using JRE_HOME:
/System/Library/Frameworks/JavaVM.framework/Versions/CurrentJDK/Home
Using CLASSPATH:
/opt/apache-tomcat-6.0.26/bin/bootstrap.jar
...
INFO - BrokerService - ActiveMQ 5.4.1 JMS Message
Broker (FooBroker) is starting
...
Apr 9, 2010 8:54:59 PM org.apache.catalina.startup.Catalina start
INFO: Server startup in 3365 ms
同样,基于FooBroker启动的输出状态你能看到ActiveMQ在使用activemq.xml配置文件。
第六步 访问 http://localhost:8080/jms-webapp并发送一个消息。
第七步 为了确认一个成功的消息发送,确认控制台下面的输出:
...
INFO: Server startup in 3365 ms
INFO - SingleConnectionFactory - Established shared
JMS Connection:
ActiveMQConnection {id=ID:mongoose.local-49429-1270868098091-2:1,
clientId=null,started=false}
INFO - JmsMessageDelegate - Consumed message with payload:
This is a test message
在显示的输出中,注意从JmsMessageDelegate Bean中的输出的最后一行显示了被JmsMessageDelegate bean消费的消息正文。
对于一些项目而言,配置ActiveMQ来使用Tomcat global JNDI context是合适的因为可能有多个项目需要访问那些资源。在一些情况下,它是有意义的,它从Tomcat内部进程中控制了ActiveMQ。缺点是Tomcat和ActiveMQ在相同的JVM正在争用同样的资源。对于一些项目,这不是一个问题,因此是一个acceptable trade-off。
但是Tomcat并被是唯一viable开源web容器。Jetty是一个formidable的选择。