7.2 Spring中集成 ActiveMQ
7.2 Embedding ActiveMQ using SpringActiveMQ is developed with Spring in mind. In fact, ActiveMQ uses a Spring XML configurationfile by default. This makes it easy to embed an ActiveMQ broker in Springenabledapplications. This section will explore numerous methods for utilizingActiveMQ with Spring. Although there are advantages and disadvantages to somemethods, and some are recommended more than others, no single method is the bestone. The decision on which method to use typically can be made by considering yourapplication and system architecture, the skill set of your developers, and the difficultyto maintain the solution once it’s deployed to your production systems. |
7.2 Spring中集成 ActiveMQActiveMQ是基于Spring思想开发的.实际上,默认情况下ActiveMQ使用Spring格式的XML配置文件.这样可以很容易的将ActiveMQ代理嵌入到使用Spring的程序中.本节将介绍几种在Spring中使用ActiveMQ的方法,这些方法各有优缺点,其中一些方法比其他的更值得推荐,不存在某个最好好的方法.开发时具体使用那种方法取决于你的程序和系统架构,开发人员技术水平以及应用部署到生成系统后系统维护方案的难易程度. |
7.2.1 Pure Spring XMLThe first style of Spring configuration to examine is what’s known as a pure Spring configuration.A pure Spring configuration is characterized by the style of the XML. It usesthe standard Spring <bean id=”…” class=”…”> style of XML in the configurationfile. This style of XML is widely known because Spring is so ubiquitous and it’s easy tounderstand. |
7.2.1 纯Spring XML配置第一种配置配置Spring的方式是使用纯Spring风格的配置.纯Spring风格的配置就是使用XML配置文件配置.在XML文件中使用标准的Spring<bean id=”…” class=”…”>标签配置.这种配置风格广为流传是因为Spring框架非常流行并且容易理解. |
Using a pure Spring XML syntax is easy to do with ActiveMQ. All you have to do isdefine the BrokerService as a bean and any dependencies in the Spring configurationfile. The following listing shows the same broker configuration that was shown inlisting 7.2. |
使用纯Spring风格的XML语法配置ActiveMQ十分容易.你要做的就是将BrokerService定义为一个bean同时在Spring配置文件中为BrokerService定义必要的依赖.下面的代码清单中配置的代理与清单7.2中的配置代理相同. |
<beans> <bean id="admins" class="org.apache.activemq.security.AuthenticationUser"> <constructor-arg index="0" value="admin" /> <constructor-arg index="1" value="password" /> <constructor-arg index="2" value="admins,publisher,consumers" /> </bean> <bean id="publishers" class="org.apache.activemq.security.AuthenticationUser"> <constructor-arg index="0" value="publisher" /> <constructor-arg index="1" value="password" /> <constructor-arg index="2" value="publisher,consumers" /> </bean> <bean id="consumers" class="org.apache.activemq.security.AuthenticationUser"> <constructor-arg index="0" value="consumer" /> <constructor-arg index="1" value="password" /> <constructor-arg index="2" value="consumers" /> </bean> <bean id="guests" class="org.apache.activemq.security.AuthenticationUser"> <constructor-arg index="0" value="guest" /> <constructor-arg index="1" value="password" /> <constructor-arg index="2" value="guests" /> </bean> <bean id="simpleAuthPlugin"class="org.apache.activemq.security.SimpleAuthenticationPlugin"> <property name="users"> <util:list> <ref bean="admins" /> <ref bean="publishers" /> <ref bean="consumers" /> <ref bean="guests" /> </util:list> </property> </bean> <bean id="broker" class="org.apache.activemq.broker.BrokerService" init-method="start" destroy-method="stop"> <property name="brokerName" value="myBroker" /> <property name="persistent" value="false" /> <property name="transportConnectorURIs"> <list> <value>tcp://localhost:61616</value> </list> </property> <property name="plugins"> <list> <ref bean="simpleAuthPlugin"/> </list> </property> </bean> </beans> |
|
As noted, the broker configuration in listing 7.6 follows exactly the same broker configurationthat was shown in listing 7.2. The difference between these two configurationsis that listing 7.2 directly makes use of the ActiveMQ Java API, and listing 7.6indirectly uses the ActiveMQ Java API by way of the Spring container and a pure Springstyle of XML. There’s no distinct advantage necessarily; this is just another availableoption. Even if you use the standard ActiveMQ XML in the config file, you can still usethe standard Spring XML syntax in that file as well. |
前面说过,清单7.6中皮质的代理与清单7.2中配置的代理是相同的.两个配置的不同点在于清单7.2直接使用的ActiveMQ的Java API,而清单7.6中通过Spring容器和纯Spring风格的XML配置文件间接使用ActiveMQ的Java API.这种配置方式没有明显的优势,只是提供了一种配置方法.即使你使用标准的ActiveMQ XML配置文件,你仍然可以使用标准的Spring XML配置文件语法. |
To start up ActiveMQ using this style of configuration, use the SpringConfig class as shown next. |
可以通过下面的命令,使用SpringConfig启动使用这种风格配置的ActiveMQ代理: |
$ mvn exec:java -Dexec.mainClass=org.apache.activemq.book.ch7.broker.SpringConfig (译注: 源码中貌似有问题,这个例子无法运行) ... 13:27:42,125 | INFO | Loading XML bean definitions from class path resource [org/apache/activemq/book/ch7/pure-spring.xml] 13:27:42,366 | INFO | Bean factory for application context[org.springframework.context.support.ClassPathXmlApplicationContext@20edbca8]:org.springframework.beans.factory.support.DefaultListableBeanFactory@7c959fa1 13:27:42,418 | INFO | Pre-instantiating singletons in org.springframework.beans.factory.support. DefaultListableBeanFactory@7c959fa1:defining beans [admins,publishers,consumers,guests,simpleAuthPlugin,broker];root of factory hierarchy 13:27:42,719 | INFO | Using Persistence Adapter: MemoryPersistenceAdapter 13:27:42,721 | INFO | ActiveMQ 5.4.1 JMS Message Broker (myBroker) is starting 13:27:42,721 | INFO | For help or more information please see:http://activemq.apache.org/ 13:27:43,224 | INFO | Listening for connections at:tcp://mongoose.local:61616 13:27:43,225 | INFO | Connector tcp://mongoose.local:61616 Started 13:27:43,227 | INFO | ActiveMQ JMS Message Broker(myBroker, ID:mongoose.local-50630-1282246062743-0:0) started Press any key to stop the broker |
|
The SpringConfig class is a simple class that uses the Spring ClassPathXml-ApplicationContext (http://mng.bz/71U2) in a main method to read in the pureSpring config and start the ActiveMQ broker. A slight variation on this style of startupis to use the BrokerFactoryBean that’s provided with ActiveMQ. |
SpringConfig类在main方法中使用Spring的lassPathXmlApplicationContext类读取Spring配置文件然后创建ActiveMQ代理.与上面这种启动代理的方式不同的是,ActiveMQ还提供了BrokerFactoryBean用来启动代理. |
7.2.2 Using the BrokerFactoryBeanIt’s common in enterprise Java development to use Spring factory beans (http://mng.bz/h0OJ) to expose beans that are themselves factories. The purpose of Springfactory beans is to instantiate a factory that requires a complex configuration. The useof the factory bean replaces writing a bunch of complex XML, and it hooks right intothe Spring container. The org.apache.activemq.xbean.BrokerFactoryBean classdoes this job for ActiveMQ. Using the BrokerFactoryBean is easier than creating andmaintaining your own class for this purpose. An ActiveMQ broker can be started upusing the BrokerFactoryBean class as shown next. |
7.2.2 使用 BrokerFactoryBean在企业级Java开发中,经常使用Spring的工厂bean(http://mng.bz/h0OJ)作为创建Bean的工厂.使用Spring工厂Bean的目的是实例化一个需要复杂配置的工厂类.使用工厂Bean可以替代书写一大段复杂的XML配置,并且具有勾取Spring容器的能力.ActiveMQ的提供org.apache.activemq.xbean.BrokerFactoryBean类作为工厂Bean类.使用BrokerFactoryBean类比你自己创建一个Broker工程Bean类来的容易些.下面的示例代码中配置饿了使用BrokerFactoryBean类来启动一个ActiveMQ代理. |
<beans> <bean id="broker" class="org.apache.activemq.xbean.BrokerFactoryBean"> <property name="config" value="org/apache/activemq/book/ch6/activemq-simple.xml"/> <property name="start" value="true" /> </bean> </beans> |
|
Note in listing 7.8 that the XML to configure the BrokerFactoryBean is minimal. Ituses a property named config to point to the standard ActiveMQ XML configurationfile that was described in earlier chapters and a property named start to instructSpring to invoke the start method on the factory bean after it’s initialized (this startsup the ActiveMQ broker instance). You can also disable this feature and simply startthe broker manually if you wish. To execute this example, see the following listing. |
注意,清单7.8中使用XML配置的BrokerFactoryBean是最小配置,它采用一个config属性指向标准的ActiveMQ XML配置文件,该文件在前面章节中介绍过;同时还使用一个start属性让Spring容器在启动并完成工厂类的初始化后调用工厂类的start(该方法将启动ActiveMQ的代理实例).你也可以设置禁用改特性,手工启动代理.下面的命令用来运行这个例子: |
$ mvn exec:java -Dexec.mainClass=org.apache.activemq.book.ch7.spring.BrokerFactoryBeanExample \
-Dlog4j.configuration=file:src/main/java/log4j.properties \ -Dexec.args="src/main/resources/org/apache/activemq/book/ch7/spring-1.0.xml" (dos命令: mvn exec:java -Dexec.mainClass=org.apache.activemq.book.ch7.spring.BrokerFactoryBeanExample ^ -Dlog4j.configuration=file:src/main/java/log4j.properties ^ -Dexec.args="src/main/resources/org/apache/activemq/book/ch7/spring-1.0.xml" 译注:修改了 pom文件,<xbean-version>2.8</xbean-version>版本换了,原来是2.6报异常.) ... [INFO] [exec:java {execution: default-cli}] Starting broker with the following configuration: src/main/resources/org/apache/activemq/book/ch7/spring-1.0.xml INFO | Using Persistence Adapter:AMQPersistenceAdapter(data/localhost) INFO | AMQStore starting using directory:data/localhost INFO | Kaha Store using data directorydata/localhost/kr-store/state INFO | Active data files: [] INFO | ActiveMQ 5.4.1 JMS Message Broker (localhost) is starting INFO | For help or more information please see:http://activemq.apache.org/ INFO | Kaha Store using data directorydata/localhost/kr-store/data INFO ManagementContext - JMX consoles can connect toservice:jmx:rmi:///jndi/rmi://localhost:1099/jmxrmi INFO | Listening for connections at: tcp://localhost:61616 INFO | Connector openwire Started INFO |ActiveMQ JMS Message Broker(localhost, ID:wfh-dejanb-65076-1269595139615-0:0) started Sending: {price=22.74502068626, stock=JAVA, offer=22.767765706954,up=true}on destination: topic://STOCKS.JAVA Sending: {price=65.23301909637, stock=IONA, offer=65.29825211547,up=true}on destination: topic://STOCKS.IONA Sending: {price=65.09672311118, stock=IONA, offer=65.16181983429,up=false}on destination: topic://STOCKS.IONA Sending: {price=64.84016157839, stock=IONA, offer=64.90500173997,up=false}on destination: topic://STOCKS.IONA Sending: {price=22.560415476111, stock=JAVA, offer=22.582975891587,up=false}on destination: topic://STOCKS.JAVA Sending: {price=64.43834994393, stock=IONA, offer=64.50278829387,up=false}on destination: topic://STOCKS.IONA Sending: {price=22.583510723322, stock=JAVA, offer=22.606094234045,up=true}on destination: topic://STOCKS.JAVA ... |
|
In listing 7.9, you should see that the broker is started using the BrokerFactoryBeanvia the Spring configuration and stock price messages are being sent to the broker.In addition to the BrokerFactoryBean, you can also use XBean with Spring. |
由代码清单7.9可见,代理(broker)是使用Spring配置的BrokerFactoryBean启动的,同时股票价格信息被正确的发送给代理了.除了使用BrokerFactoryBean外,你还可以通过Spring使用XBean. |
7.2.3 Using Apache XBean with SpringBy default, ActiveMQ uses Spring and Apache XBean (http://mng.bz/EAfX) for itsinternal configuration purposes. Therefore all activemq.xml files we used in previouschapters to configure various features of ActiveMQ are basically Spring configurationfiles, powered by an XBean custom XML schema. XBean provides the ability to defineand use a custom XML syntax that’s much more compact than the standard SpringXML syntax. Although Spring provides the ability to do this now, such features weren’tavailable when ActiveMQ was created (Spring only supported DTDs at the time).The following listing shows an example of a simple Java application using Springand XBean. |
7.2.3 Spring中使用Apache XBean默认情况下,ActiveMQ使用Spring和Apache XBean(http://mng.bz/EAfX)进行配置.因此,前面章节中用来配置各种功能的activemq.xml文件基本都是一种称为XBean的自定义XML schema的Spring格式的配置文件.XBean提供一种比标准Spring XML语法更复杂的自定义XML语法.尽管现在Spring已支持这种自定义XML语法,但是Spring在ActiveMQ出现之后才提供这种功能(ActiveMQ出现时,Spring仅支持DTDs).下面的代码清单是普通Java程序中使用Spring和XBean的示例: |
package org.apache.activemq.book.ch7.xbean; import org.apache.activemq.book.ch6.Publisher; import org.apache.xbean.spring.context.FileSystemXmlApplicationContext; public class XBeanBroker { public static void main(String[] args) throws Exception { if (args.length == 0) { System.err.println("Please define a configuration file!"); return; } String config = args[0]; System.out.println("Starting broker with the following configuration: " + config); System.setProperty("activemq.base", System.getProperty("user.dir")); FileSystemXmlApplicationContext context = new FileSystemXmlApplicationContext(config); Publisher publisher = new Publisher(); for (int i = 0; i < 100; i++) { publisher.sendMessage(new String[]{"JAVA", "IONA"}); } } } |
|
Listing 7.10 accepts an argument for the path to the XML configuration file, sets theactivemq.base system property, and instantiates a Spring application context usingthe XML configuration file. Then the publisher is instantiated and used to send a simplemessage 100 times. That’s the entire application. Everything else that’s needed ishandled by ActiveMQ and the Spring Framework. Please note that the applicationcontext class used in this example is from XBean, not the Spring Framework. Thisexample can be run using the command shown in the following listing. |
代码清单7.10中的类接收一个指向XML配置文件路径的命令行参数,并设置了activemq.base系统参数,然后使用上述参数指定的XML配置文件初始化Spring容器.接下来,程序初始化了publisher类并用它发送100次普通消息.整个程序的功能就是这样,其他必要的工作都由ActiveMQ和Spring框架完成.请注意,本例中使用的FileSystemXmlApplicationContext类来自XBean而不是来自Spring框架.可以使用下面的命令来运行这个例子: |
$ mvn exec:java -Dexec.mainClass=org.apache.activemq.book.ch7.xbean.XBeanBroker \ -Dlog4j.configuration=file:src/main/java/log4j.properties \ -Dexec.args= "src/main/resources/org/apache/activemq/book/ch6/activemq-simple.xml" (译注:dos命令: mvn exec:java -Dexec.mainClass=org.apache.activemq.book.ch7.xbean.XBeanBroker ^ -Dlog4j.configuration=file:src/main/java/log4j.properties ^ -Dexec.args="src/main/resources/org/apache/activemq/book/ch6/activemq-simple.xml" ) ... [INFO] [exec:java {execution: default-cli}] Starting broker with the following configuration: src/main/resources/org/apache/activemq/book/ch6/activemq-simple.xml INFO | Using Persistence Adapter: AMQPersistenceAdapter(data/localhost) INFO | AMQStore starting using directory: data/localhost INFO | Kaha Store using data directory data/localhost/kr-store/state INFO | Active data files: [] INFO | ActiveMQ 5.4.1 JMS Message Broker (localhost) is starting INFO | For help or more information please see: http://activemq.apache.org/ INFO | Kaha Store using data directory data/localhost/kr-store/data INFO | JMX consoles can connect to service:jmx:rmi:///jndi/rmi://localhost:1099/jmxrmi INFO | Listening for connections at: tcp://localhost:61616 INFO | Connector openwire Started INFO | ActiveMQ JMS Message Broker (localhost, ID:dejanb-65363-1269596340878-0:0) started Sending: {price=53.794098159875, stock=IONA, offer=53.847892258035,up=false}on destination: topic://STOCKS.IONA Sending: {price=53.489740886575, stock=IONA, offer=53.543230627461,up=false}on destination: topic://STOCKS.IONA Sending: {price=53.5342708859, stock=IONA, offer=53.58780515680,up=true}on destination: topic://STOCKS.IONA Sending: {price=53.86122035252, stock=IONA, offer=53.91508157288,up=true}on destination: topic://STOCKS.IONA Sending: {price=54.15343454330, stock=IONA, offer=54.207587977851,up=true}on destination: topic://STOCKS.IONA Sending: {price=49.27384513708, stock=JAVA, offer=49.323118982218,up=false}on destination: topic://STOCKS.JAVA Sending: {price=53.83373859262, stock=IONA, offer=53.8875723312,up=false}on destination: topic://STOCKS.IONA Sending: {price=53.933391780045, stock=IONA, offer=53.98732517182,up=true}on destination: topic://STOCKS.IONA ... |
|
The broker that’s started behaves the same as the previously defined examples.In addition to the compact XML syntax provided by XBean, Spring also supportXML namespaces. |
上面命令启动了一个和前面例子中功能一样的代理.除了支持XBean提供的复杂XML语法为,Spring也支持XML命令空间. |
7.2.4 Using a custom XML namespace with SpringAll recent versions of the Spring Framework allow developers to utilize a custom XMLschema. ActiveMQ provides a custom XML schema to configure ActiveMQ via theSpring configuration file. The following listing demonstrates how to configureActiveMQ using its custom Spring schema via an XML namespace. |
7.2.4 Spring中使用自定义XML命名空间当前版本的Spring框架允许开发者使用自定义的XML模式(schema).ActiveMQ提供一种自定义XML模式(schema)用于在Spring配置文件中配置ActiveMQ.下面的代码清单说明了如何通过自定义的Spring schema作为XML命名空间来配置ActiveMQ: |
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:amq="http://activemq.apache.org/schema/core" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd http://activemq.apache.org/schema/core http://activemq.apache.org/schema/core/activemq-core.xsd"> <amq:broker brokerName="localhost" dataDirectory="${activemq.base}/data"> <amq:transportConnectors> <amq:transportConnector name="openwire" uri="tcp://localhost:61616" /> </amq:transportConnectors> <amq:plugins> <amq:simpleAuthenticationPlugin> <amq:users> <amq:authenticationUser username="admin" password="password" groups="admins,publishers,consumers"/> <amq:authenticationUser username="publisher" password="password" groups="publishers,consumers"/> <amq:authenticationUser username="consumer" password="password" groups="consumers"/> <amq:authenticationUser username="guest" password="password" groups="guests"/> </amq:users> </amq:simpleAuthenticationPlugin> </amq:plugins> </amq:broker> </beans> |
|
As you can see in listing 7.12, first a prefix is declared that will be used throughout theXML document to reference element types from the custom schema. The prefix that’scommonly used for ActiveMQ is amq. Second is the URI to the right of the prefix,which in this case is http://activemq.apache.org/schema/core. The prefix is used toreference the URI from within the XML document. Third, the URI is used as an identifierto point to the actual location of the XML schema document (XSD) via theschemaLocation attribute. For example, when the <amq:broker> element is used, theamq prefix serves as an alias to the URI and the URI points to the XSD where the brokerelement can be found. |
在代码清单7.12中你可以看到,首先,定义了一个前缀,在XML文档中使用该前缀用于引用自定义的模式中的元素类型.通常,ActiveMQ在XML文件中使用amq作为XML模式前缀;第二,前缀右边的URI,即http://activemq.apache.org/schema/core,前缀用来引用来自URI指定文档中定义的元素类型;第三,URI用来通过schemaLocation属性指向实际XML模式文档(XSD)的位置.例如,使用<amq:broker> 后,前缀amq可以作为URI的别名指向定义了broker元素的XSD文档. |
Once the XML namespace is declared, we’re free to define our broker-relatedbeans using the custom XML syntax. In this particular example we’ve configured thebroker as it was configured in our previously used chapter 6 example, with the simpleauthentication plug-in. Now the Spring broker can be started as shown next. |
一旦定义了XML命名空间,我们就可以使用自定义的XML语法来配置代理相关的Bean了.本例中配置的代理和前面第6章中配置的相同,使用了简单认证插件.下面可以使用下面的命令来启动这个Spring中配置的代理: |
$ mvn -e exec:java -Dexec.mainClass=org.apache.activemq.book.ch7.spring.SpringBroker / -Dlog4j.configuration=file:src/main/java/log4j.properties / -Dexec.args=src/main/resources/org/apache/activemq/book/ch7/spring-2.0.xml 译注:dos代码: public class SpringBroker { public static void main(String[] args) throws Exception { if (args.length == 0) { //System.err.println("Please define a configuration file!"); //return; } String config = "src/main/resources/org/apache/activemq/book/ch7/spring-2.0.xml"; System.out.println("Starting broker with the following configuration: " + config); System.setProperty("activemq.base", System.getProperty("user.dir")); FileSystemXmlApplicationContext context = new FileSystemXmlApplicationContext(config); Publisher publisher = new Publisher(); for (int i = 0; i < 100; i++) { publisher.sendMessage(new String[]{"JAVA", "IONA"}); } } } 注意 写死了 String config = “src/main/resources/org/apache/activemq/book/ch7/spring-2.0.xml”; 这个文件 ... [INFO] [exec:java {execution: default-cli}] Starting broker with the following configuration: src/main/resources/org/apache/activemq/book/ch7/spring-2.0.xml INFO | Using Persistence Adapter: AMQPersistenceAdapter(${activemq.base}/data/localhost) INFO | AMQStore starting using directory: data/localhost INFO | Kaha Store using data directory data/localhost/kr-store/state INFO | Active data files: [] INFO | ActiveMQ 5.4.1 JMS Message Broker (localhost) is starting INFO | For help or more information please see: http://activemq.apache.org/ INFO | Kaha Store using data directory data/localhost/kr-store/data INFO | JMX consoles can connect to service:jmx:rmi:///jndi/rmi://localhost:1099/jmxrmi INFO | Listening for connections at: tcp://localhost:61616 INFO | Connector openwire Started INFO | ActiveMQ JMS Message Broker (localhost, ID:dejanb-65324-1269595874364-0:0) started Sending: {price=83.53568740848, stock=IONA, offer=83.61922309589, up=true}on destination: topic://STOCKS.IONA Sending: {price=84.15670625187, stock=IONA, offer=84.24086295812, up=true}on destination: topic://STOCKS.IONA Sending: {price=83.64752134809, stock=IONA, offer=83.7311688694, up=false}on destination: topic://STOCKS.IONA Sending: {price=83.33023218494, stock=IONA, offer=83.41356241712, up=false}on destination: topic://STOCKS.IONA Sending: {price=84.05476877613, stock=IONA, offer=84.13882354490, up=true}on destination: topic://STOCKS.IONA Sending: {price=57.75764610250, stock=JAVA, offer=57.815403748606, up=true}on destination: topic://STOCKS.JAVA Sending: {price=84.3813034823, stock=IONA, offer=84.46568478585, up=true}on destination: topic://STOCKS.IONA Sending: {price=84.77874758495, stock=IONA, offer=84.86352633253, up=true}on destination: topic://STOCKS.IONA ... |
|
The example shown in listing 7.13 uses the most common type of XML configurationfile. So although this is nothing new, it’s something that many developers don’t fullyunderstand. |
代码清单7.13中使用了最常用的XML配置文件,所以尽管没有什么新东西,但是很多开发者不能完全理解这样的配置. |
Now that we’ve examined and demonstrated various styles of configuration examplesfor ActiveMQ, it’s time to shift gears a bit to look at a common use of ActiveMQ:creating an application that uses a common JMS paradigm known as request/reply. |
我们已经讨论了多种风格的配置文件实例,现在让我们换个内容看看ActiveMQ的基本用法:创建一个基于请求/应答的JMS示例程序. |
微信赞赏 支付宝赞赏
本文固定链接: https://www.jack-yin.com/coding/translation/activemq-in-action/1552.html | 边城网事