﻿<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/"><channel><title>BlogJava-Terry.B.Li           彬-文章分类-JMS</title><link>http://www.blogjava.net/libin2722/category/37068.html</link><description>虚其心，可解天下之问；专其心，可治天下之学；静其心，可悟天下之理；恒其心，可成天下之业。</description><language>zh-cn</language><lastBuildDate>Tue, 07 Sep 2010 04:04:36 GMT</lastBuildDate><pubDate>Tue, 07 Sep 2010 04:04:36 GMT</pubDate><ttl>60</ttl><item><title>JGroups</title><link>http://www.blogjava.net/libin2722/articles/330636.html</link><dc:creator>礼物</dc:creator><author>礼物</author><pubDate>Wed, 01 Sep 2010 14:43:00 GMT</pubDate><guid>http://www.blogjava.net/libin2722/articles/330636.html</guid><wfw:comment>http://www.blogjava.net/libin2722/comments/330636.html</wfw:comment><comments>http://www.blogjava.net/libin2722/articles/330636.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/libin2722/comments/commentRss/330636.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/libin2722/services/trackbacks/330636.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: 1 Overview    JGroups是一个用于建立可靠的组播通信的工具包（这里指的组播并不一定是IP Multicast，JGroups同样支持使用TCP作为传输协议）。其中可靠性是指通过适当的配置可以保证：消息在传输的过程中不会丢失；所有的接收者以相同的顺序接受所有的消息；原子性：一个消息要么被所有的接收者接收，要么不被任何一个接收者都接收。目前在JBoss Applicati...&nbsp;&nbsp;<a href='http://www.blogjava.net/libin2722/articles/330636.html'>阅读全文</a><img src ="http://www.blogjava.net/libin2722/aggbug/330636.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/libin2722/" target="_blank">礼物</a> 2010-09-01 22:43 <a href="http://www.blogjava.net/libin2722/articles/330636.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>JMX Remoting</title><link>http://www.blogjava.net/libin2722/articles/330634.html</link><dc:creator>礼物</dc:creator><author>礼物</author><pubDate>Wed, 01 Sep 2010 14:34:00 GMT</pubDate><guid>http://www.blogjava.net/libin2722/articles/330634.html</guid><wfw:comment>http://www.blogjava.net/libin2722/comments/330634.html</wfw:comment><comments>http://www.blogjava.net/libin2722/articles/330634.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/libin2722/comments/commentRss/330634.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/libin2722/services/trackbacks/330634.html</trackback:ping><description><![CDATA[
		<div class="blog_content">
				<p>1 Introduction<br />    Java Management Extension (JMX) API定义于JSR 
3，用于应用程序管理。这些API对于被管理的应用程序来说是本地的。也就是说，在JSR 
160发布之前，如果客户端要通过JMX来管理和监控远程的应用程序，并没有标准的做法。JSR 160扩展了JSR 
3，提供了标准的API用于连接到支持JMX的远程应用程序。JSR 255将会把JMX升级到2.0，并可能体现在Java 7中。<br />    目前JSR 160定义了基于RMI（支持RMI/JRMP 和 RMI/IIOP）的连接器，还定义了可选的JMXMP连接器，它基于TCP Socket和Java序列化机制。</p>
				<p> </p>
				<p>2 JMX Remoting API<br />2.1 JMXServiceURL<br />    JMXServiceURL用于标识JMXConnectorServer，它是采用以下形式的字符串：<br />    service:jmx:&lt;protocol&gt;://[[[ &lt;host&gt;]: &lt;port&gt;]/ &lt;path&gt;]<br />   
 "protocol" 指定了协议，例如：rmi、iiop、jmxmp 或者 soap。"host"、"port" 和 
"path"是可选的。JMXServiceURL并不足以描述所有的用于连接到JMXConnectorServer的配置信息（例如配置
RMIClientSocketFactory 和RMIServerSocketFactory），因此在构造JMXConnectorServer 和
 JMXConnector的时候，还可能需要通过一个Map实例指定其它属性。</p>
				<p> </p>
				<p>2.2 JMXConnectorServer<br />    JMXConnectorServer 
是MBeanServer端的组件，它需要被关联到MBeanServer：可以通过在创建JMXConnectorServer的时候显式指定
MBeanServer；也可以把JMXConnectorServer（本身是一个MBean）注册到MBeanServer中。<br />    
在被关联到MBeanServer之后，需要启动JMXConnectorServer以处理客户端的请求。同样，如果希望停止处理客户端的请求，那么需
要停止JMXConnectorServer。JMXConnectorServer被停止之后，不应该试图重新启动它，而是应该将其丢弃。<br />    最好通过JMXConnectorServerFactory来创建JMXConnectorServer，例如：</p>
				<div class="dp-highlighter">
						<div class="bar">
								<div class="tools">Java代码 </div>
						</div>
						<ol class="dp-j" start="1">
								<li>
										<span>
												<span class="comment">// The address of the connector server</span>
												<span>  </span>
										</span>
								</li>
								<li>
										<span>JMXServiceURL address = <span class="keyword">new</span><span> JMXServiceURL(</span><span class="string">"service:jmx:rmi://host"</span><span>);  </span></span>
								</li>
								<li>
										<span>  </span>
								</li>
								<li>
										<span>
												<span class="comment">// The environment map, null in this case</span>
												<span>  </span>
										</span>
								</li>
								<li>
										<span>Map environment = <span class="keyword">null</span><span>;  </span></span>
								</li>
								<li>
										<span>  </span>
								</li>
								<li>
										<span>
												<span class="comment">// The MBeanServer to which the JMXConnectorServer will be attached to</span>
												<span>  </span>
										</span>
								</li>
								<li>
										<span>MBeanServer server = MBeanServerFactory.createMBeanServer();  </span>
								</li>
								<li>
										<span>  </span>
								</li>
								<li>
										<span>
												<span class="comment">// Create the JMXCconnectorServer</span>
												<span>  </span>
										</span>
								</li>
								<li>
										<span>JMXConnectorServer cntorServer = JMXConnectorServerFactory.newJMXConnectorServer(address, environment, server);  </span>
								</li>
								<li>
										<span>  </span>
								</li>
								<li>
										<span>
												<span class="comment">// Start the JMXConnectorServer</span>
												<span>  </span>
										</span>
								</li>
								<li>
										<span>cntorServer.start();  </span>
								</li>
						</ol>
				</div>
				<p>    在以上的例子中，创建JMXConnectorServer的时候指定了MBeanServer。以下是一个将JMXConnectorServer作为MBean注册到MBeanServer的例子：</p>
				<div class="dp-highlighter">
						<div class="bar">
								<div class="tools">Java代码 </div>
						</div>
						<ol class="dp-j" start="1">
								<li>
										<span>
												<span class="comment">// The address of the connector</span>
												<span>  </span>
										</span>
								</li>
								<li>
										<span>JMXServiceURL address = <span class="keyword">new</span><span> JMXServiceURL(</span><span class="string">"service:jmx:rmi://host"</span><span>);  </span></span>
								</li>
								<li>
										<span>  </span>
								</li>
								<li>
										<span>
												<span class="comment">// The environment map, null in this case</span>
												<span>  </span>
										</span>
								</li>
								<li>
										<span>Map environment = <span class="keyword">null</span><span>;  </span></span>
								</li>
								<li>
										<span>  </span>
								</li>
								<li>
										<span>JMXConnectorServer cntorServer = JMXConnectorServerFactory.newJMXConnectorServer(address, environment, <span class="keyword">null</span><span>);  </span></span>
								</li>
								<li>
										<span>  </span>
								</li>
								<li>
										<span>
												<span class="comment">// The MBeanServer to which the JMXConnectorServer will be registered in</span>
												<span>  </span>
										</span>
								</li>
								<li>
										<span>MBeanServer server = MBeanServerFactory.createMBeanServer();  </span>
								</li>
								<li>
										<span>  </span>
								</li>
								<li>
										<span>
												<span class="comment">// Register the JMXConnectorServer in the MBeanServer</span>
												<span>  </span>
										</span>
								</li>
								<li>
										<span>ObjectName cntorServerName = ObjectName.getInstance(<span class="string">"connectors:protocol=rmi"</span><span>);  </span></span>
								</li>
								<li>
										<span>server.registerMBean(cntorServer, cntorServerName);  </span>
								</li>
								<li>
										<span>  </span>
								</li>
								<li>
										<span>
												<span class="comment">// Start the JMXConnectorServer</span>
												<span>  </span>
										</span>
								</li>
								<li>
										<span>cntorServer.start();  </span>
								</li>
								<li>
										<span>  </span>
								</li>
								<li>
										<span>
												<span class="comment">// An alternative way to start the JMXConnectorServer via the MBeanServer</span>
												<span>  </span>
										</span>
								</li>
								<li>
										<span>server.invoke(cntorServerName, <span class="string">"start"</span><span>, </span><span class="keyword">null</span><span>, </span><span class="keyword">null</span><span>);  </span></span>
								</li>
								<li>
										<span>  </span>
								</li>
								<li>
										<span>
												<span class="comment">// Yet another way to start the JMXConnectorServer via the MBeanServer</span>
												<span>  </span>
										</span>
								</li>
								<li>
										<span>Object proxy = MBeanServerInvocationHandler.newProxyInstance(server, cntorServerName, JMXConnectorServerMBean.<span class="keyword">class</span><span>, </span><span class="keyword">true</span><span>);  </span></span>
								</li>
								<li>
										<span>JMXConnectorServerMBean cntorServerMBean = (JMXConnectorServerMBean)proxy;  </span>
								</li>
								<li>
										<span>cntorServerMBean.start();  </span>
								</li>
						</ol>
				</div>
				<p>    
需要注意的是，在这个例子中使用了三种不同的方式启动JMXConnectorServer：第一种方式是直接调用cntorServer对象的
start方法；第二种方式是通过MBeanServer调用MBean的方法；第三种方式是使用了
MBeanServerInvocationHandler，它继承自InvocationHandler，用于从MBean的管理接口向
MBeanServer中的 MBean 
转发方法调用。当调用从newProxyInstance()方法返回的代理对象上的toString()、hashCode() 
和equals(Object)等方法时，这些方法调用同样也会被转发到MBeanServer中的MBean ，因此当且仅当 MBean 
在其管理接口中声明了这些方法时才能如此操作，否则会抛出异常。</p>
				<p> </p>
				<p>2.3 JMXConnector<br />   
JMXConnector是客户端的组件，客户端程序通过它连接到远程的MBeanServer。客户端可以通过JMXConnector获得远程
MBeanServer的MBeanServerConnection 
接口，并以类似本地的方式使用它。JMXConnector还支持在远程的MBeanServer上注册本地或者远程的通知监听器，以接收来自远程
MBeanServer的通知。<br />    最好通过JMXConnectorFactory来创建JMXConnector，例如：</p>
				<div class="dp-highlighter">
						<div class="bar">
								<div class="tools">Java代码 </div>
						</div>
						<ol class="dp-j" start="1">
								<li>
										<span>
												<span class="comment">// The address of the connector server</span>
												<span>  </span>
										</span>
								</li>
								<li>
										<span>JMXServiceURL address = ...;  </span>
								</li>
								<li>
										<span>  </span>
								</li>
								<li>
										<span>
												<span class="comment">// The environment map, null in this case</span>
												<span>  </span>
										</span>
								</li>
								<li>
										<span>Map environment = <span class="keyword">null</span><span>;  </span></span>
								</li>
								<li>
										<span>  </span>
								</li>
								<li>
										<span>
												<span class="comment">// Create the JMXCconnectorServer</span>
												<span>  </span>
										</span>
								</li>
								<li>
										<span>JMXConnector cntor = JMXConnectorFactory.connect(address, environment);  </span>
								</li>
								<li>
										<span>  </span>
								</li>
								<li>
										<span>
												<span class="comment">// Obtain a "stub" for the remote MBeanServer</span>
												<span>  </span>
										</span>
								</li>
								<li>
										<span>MBeanServerConnection mbsc = cntor.getMBeanServerConnection();  </span>
								</li>
								<li>
										<span>  </span>
								</li>
								<li>
										<span>
												<span class="comment">// Call the remote MBeanServer</span>
												<span>  </span>
										</span>
								</li>
								<li>
										<span>String domain = mbsc.getDefaultDomain();  </span>
								</li>
								<li>
										<span>也可以先实例化JMXConnector，然后在连接到MBeanServer，例如：  </span>
								</li>
								<li>
										<span>
												<span class="comment">// The address of the connector server</span>
												<span>  </span>
										</span>
								</li>
								<li>
										<span>JMXServiceURL address = ...;  </span>
								</li>
								<li>
										<span>  </span>
								</li>
								<li>
										<span>
												<span class="comment">// The creation environment map, null in this case</span>
												<span>  </span>
										</span>
								</li>
								<li>
										<span>Map creationEnvironment = <span class="keyword">null</span><span>;  </span></span>
								</li>
								<li>
										<span>  </span>
								</li>
								<li>
										<span>
												<span class="comment">// Create the JMXCconnectorServer</span>
												<span>  </span>
										</span>
								</li>
								<li>
										<span>JMXConnector cntor = JMXConnectorFactory.newJMXConnector(address, creationEnvironment);  </span>
								</li>
								<li>
										<span>  </span>
								</li>
								<li>
										<span>
												<span class="comment">// The connection environment map, null in this case</span>
												<span>  </span>
										</span>
								</li>
								<li>
										<span>
												<span class="comment">// May contain - for example - user's credentials</span>
												<span>  </span>
										</span>
								</li>
								<li>
										<span>Map connectionEnvironment = <span class="keyword">null</span><span>;  </span></span>
								</li>
								<li>
										<span>  </span>
								</li>
								<li>
										<span>
												<span class="comment">// Connect</span>
												<span>  </span>
										</span>
								</li>
								<li>
										<span>cntor.connect(connectionEnvironment);  </span>
								</li>
								<li>
										<span>  </span>
								</li>
								<li>
										<span>
												<span class="comment">// Obtain a "stub" for the remote MBeanServer</span>
												<span>  </span>
										</span>
								</li>
								<li>
										<span>MBeanServerConnection mbsc = cntor.getMBeanServerConnection();  </span>
								</li>
								<li>
										<span>  </span>
								</li>
								<li>
										<span>
												<span class="comment">// Call the remote MBeanServer</span>
												<span>  </span>
										</span>
								</li>
								<li>
										<span>String domain = mbsc.getDefaultDomain();  </span>
								</li>
						</ol>
				</div>
				<p>    
需要注意的是，以上的例子中采用了两个不同的Map对象保存相关的属性：一个用于实例化；另外一个用于连接。MBeanServerConnection
接口在JMX 1.2中定义，用于支持remote 
API。由于之前版本的MBeanServer接口不能直接被客户端使用（例如其registerMBean(), deserialize(), 
getClassLoader()等方法对于客户端来说没有意义），因此在JMX 
1.2中，MBeanServer接口继承自MBeanServerConnection接口。<br /><br />    
RMIConnector是标准的JMXConnector。由于它使用RMI协议，因此需要一个stub 
object来处理RMI调用的细节。stub class通常存在于客户端的类路径上，但是stub 
object通常是从命名服务器处下载，因此RMI客户端需要知道stub object被绑定到RMI server上的路径。JSR 
160定义了两种获得stub object的方式：<br />    第一种方式不需要命名服务器，而是将stub 
object编码为JMXServiceURL的一部分，即"encoded form"。如果采用RMI/JRMP协议，那么对stub 
object被序列化之后的所有字节进行Base64编码，然后将编码后的字符添加到JMXServiceURL中，并且以/stub/开始；如果采用
RMI/ IIOP，那么IOR被添加到JMXServiceURL中，并以/ior/开始。以下是个例子：</p>
				<div class="dp-highlighter">
						<div class="bar">
								<div class="tools">Java代码 </div>
						</div>
						<ol class="dp-j" start="1">
								<li>
										<span>
												<span class="comment">// JRMP encoded form</span>
												<span>  </span>
										</span>
								</li>
								<li>
										<span>service:jmx:rmi:<span class="comment">//localhost/stub/rO0ABXNyAC5qYXZheC5tYW5hZ2VtZW50LnJlbW90ZS5ybWkuUk1JU2VydmVySW1wbF9TdHViAAAAAAAAAAICAAB4cgAaamF2YS5ybWkuc2VydmVyLlJlbW90ZVN0dWLp/tzJi+FlGgIAAHhyABxqYXZhLnJtaS5zZXJ2ZXIuUmVtb3RlT2JqZWN002G0kQxhMx4DAAB4cHc5AAtVbmljYXN0UmVmMgAADjE2LjE5Mi4xMjAuMTI5AAANcQAAAAAAAAAIAOgIQgAAAPlXjcJugAEAeA==</span><span>  </span></span>
								</li>
								<li>
										<span>  </span>
								</li>
								<li>
										<span>
												<span class="comment">// IIOP encoded form</span>
												<span>  </span>
										</span>
								</li>
								<li>
										<span>service:jmx:iiop:<span class="comment">//localhost/ior/IOR:000000000000003b524d493a6a617661782e6d616e6167656d656e742e72656d6f74652e726d692e524d495365727665723a303030303030303030303030303030300000000000010000000000000068000102000000000f31362e3139322e3132302e31323900000d93000000000019afabcb0000000002578f08b80000000800000000000000000a0000000000000100000001000000200000000000010001000000020501000100010020000101090000000100010100</span><span>  </span></span>
								</li>
						</ol>
				</div>
				<p>    第二种方式是在JMXServiceURL中指定命名服务器和stub object被绑定到的JNDI路径，即"JNDI 
form"。在JMXServiceURL中以/jndi/开始。将JNDI的相关配置传递给RMIConnector的方式有多种。例如URL 
'rmi://namingHost:1099/jndiPath'指明命名服务器在名为'namingHost'的主机上并监听1099端口，命名服务
器是rmiregistry，路径是'/jndiPath'。同样URL 
'iiop://namingHost:900/jndiPath'指明命名服务器在名为'namingHost'的主机上并监听900端口，命名服务器
是COS命名服务，路径是'/jndiPath'。以下是个例子：</p>
				<div class="dp-highlighter">
						<div class="bar">
								<div class="tools">Java代码 </div>
						</div>
						<ol class="dp-j" start="1">
								<li>
										<span>
												<span class="comment">// JNDI URL form for JRMP</span>
												<span>  </span>
										</span>
								</li>
								<li>
										<span>service:jmx:rmi:<span class="comment">//rmiHost/jndi/rmi://namingHost:1099/jndiPath</span><span>  </span></span>
								</li>
								<li>
										<span>  </span>
								</li>
								<li>
										<span>
												<span class="comment">// JNDI URL form for IIOP</span>
												<span>  </span>
										</span>
								</li>
								<li>
										<span>service:jmx:iiop:<span class="comment">//rmiHost/jndi/iiop://namingHost:900/jndiPath</span><span>  </span></span>
								</li>
						</ol>
				</div>
				<p>    
此外，JNDI属性也可以通过系统属性、类路径上的'jndi.properties'文件、在调用JMXConnector.connect(Map 
environment)或者JMXConnectorFactory.connect(JMXServiceURL url, Map 
environment)方法时传递的environment参数等不同方式指定。如果JNDI属性通过这些方式指定，那么JMXServiceURL中
可以使用简短的JNDI格式，即只指定JNDI path。以下是个例子：</p>
				<div class="dp-highlighter">
						<div class="bar">
								<div class="tools">Java代码 </div>
						</div>
						<ol class="dp-j" start="1">
								<li>
										<span>
												<span class="comment">// JNDI short form for JRMP</span>
												<span>  </span>
										</span>
								</li>
								<li>
										<span>service:jmx:rmi:<span class="comment">//rmiHost/jndi/jndiPath</span><span>  </span></span>
								</li>
								<li>
										<span>  </span>
								</li>
								<li>
										<span>
												<span class="comment">// JNDI short form for IIOP</span>
												<span>  </span>
										</span>
								</li>
								<li>
										<span>service:jmx:iiop:<span class="comment">//rmiHost/jndi/jndiPath</span><span>  </span></span>
								</li>
								<li>
										<span>  </span>
								</li>
								<li>
										<span>
												<span class="comment">// Code example that uses the JNDI short form specifying JNDI properties via environment Map</span>
												<span>  </span>
										</span>
								</li>
								<li>
										<span>
												<span class="comment">// The JNDI environment</span>
												<span>  </span>
										</span>
								</li>
								<li>
										<span>Map environment = <span class="keyword">new</span><span> HashMap();  </span></span>
								</li>
								<li>
										<span>environment.put(Context.INITIAL_CONTEXT_FACTORY, <span class="string">"com.sun.jndi.rmi.registry.RegistryContextFactory"</span><span>);  </span></span>
								</li>
								<li>
										<span>environment.put(Context.PROVIDER_URL, <span class="string">"rmi://namingHost:1099"</span><span>);  </span></span>
								</li>
								<li>
										<span>
												<span class="comment">// The JNDI short form JMXServiceURL</span>
												<span>  </span>
										</span>
								</li>
								<li>
										<span>JMXServiceURL url = <span class="keyword">new</span><span> JMXServiceURL(</span><span class="string">"service:jmx:rmi://rmiHost/jndi/jndiPath"</span><span>);  </span></span>
								</li>
								<li>
										<span>
												<span class="comment">// Connect to the server side</span>
												<span>  </span>
										</span>
								</li>
								<li>
										<span>JMXConnector connector = JMXConnectorFactory.connect(url, environment);  </span>
								</li>
						</ol>
				</div>
				<p> </p>
				<p>2.4 Remote Notification<br />    JSR 
160定义的连接器可以接收到远程MBean发送的通知。通知被传递的细节依赖于连接器使用的协议。要接收通知，客户端必须要通过调用
MBeanServerConnection.addNotificationListener(...)方法来注册一个监听器，这个方法有两个重载的版
本：<br />    第一个版本接受一个ObjectName实例作为监听器，由于监听器是远程MBeanServer中的一个MBean，因此方法中的filter和handback参数必须被传递到远程的MBeanServer，因此它们必须是可以被序列化的。<br />   
 
另一个版本接受NotificationListener的实例作为监听器。这个监听器是客户端的本地对象，而且监听器对象不会被传递到远程的
MBeanServer，因此它也不必是可以被序列化的。NotificationFilter是否被传递到远程的MBeanServer取决于
connector使用的协议，handback对象不会被传递到远程MBeanServer。在另一方面，远程的MBean发送的通知必须是可以被序列
化的，因为通知会被传递到客户端。以下是在远程的MBean上注册监听器的例子：</p>
				<div class="dp-highlighter">
						<div class="bar">
								<div class="tools">Java代码 </div>
						</div>
						<ol class="dp-j" start="1">
								<li>
										<span>
												<span class="comment">// The address of the connector server</span>
												<span>  </span>
										</span>
								</li>
								<li>
										<span>JMXServiceURL address = ...;  </span>
								</li>
								<li>
										<span>  </span>
								</li>
								<li>
										<span>
												<span class="comment">// The JMXConnector</span>
												<span>  </span>
										</span>
								</li>
								<li>
										<span>JMXConnector connector = JMXConnectorFactory.connect(address);  </span>
								</li>
								<li>
										<span>  </span>
								</li>
								<li>
										<span>
												<span class="comment">// The MBeanServerConnection "stub"</span>
												<span>  </span>
										</span>
								</li>
								<li>
										<span>MBeanServerConnection mbsc = connector.getMBeanServerConnection();  </span>
								</li>
								<li>
										<span>  </span>
								</li>
								<li>
										<span>
												<span class="comment">// The MBeanServerDelegate emits notifications about registration/unregistration of MBeans</span>
												<span>  </span>
										</span>
								</li>
								<li>
										<span>ObjectName delegateName = ObjectName.getInstance(<span class="string">"JMImplementation:type=MBeanServerDelegate"</span><span>);  </span></span>
								</li>
								<li>
										<span>  </span>
								</li>
								<li>
										<span>NotificationListener listener = <span class="keyword">new</span><span> NotificationListener()  </span></span>
								</li>
								<li>
										<span>{  </span>
								</li>
								<li>
										<span>   <span class="keyword">public</span><span> </span><span class="keyword">void</span><span> handleNotification(Notification notification, Object handback)  </span></span>
								</li>
								<li>
										<span>   {  </span>
								</li>
								<li>
										<span>      <span class="comment">// Do something</span><span>  </span></span>
								</li>
								<li>
										<span>   }  </span>
								</li>
								<li>
										<span>};  </span>
								</li>
								<li>
										<span>  </span>
								</li>
								<li>
										<span>mbsc.addNotificationListener(delegateName, listener, <span class="keyword">null</span><span>, </span><span class="keyword">null</span><span>);  </span></span>
								</li>
						</ol>
				</div>
				<p> </p>
				<p>3 JMX Remoting Security<br />    JSR 
160提供了一种可插拔的认证机制，它基于JMXAuthenticator接口。JMXAuthenticator接口中只包含如下一个方法，它接受从
客户端得到的身份证明信息作为参数，返回javax.security.auth.Subject对象的一个实例。</p>
				<div class="dp-highlighter">
						<div class="bar">
								<div class="tools">Java代码 </div>
						</div>
						<ol class="dp-j" start="1">
								<li>
										<span>
												<span class="keyword">public</span>
												<span> Subject authenticate(Object credentials) </span>
												<span class="keyword">throws</span>
												<span> SecurityException  </span>
										</span>
								</li>
						</ol>
				</div>
				<p>    以下是在JMXConnectorServer 中使用JMXAuthenticator的例子：</p>
				<div class="dp-highlighter">
						<div class="bar">
								<div class="tools">Java代码 </div>
						</div>
						<ol class="dp-j" start="1">
								<li>
										<span>
												<span class="comment">// The address of the connector server</span>
												<span>  </span>
										</span>
								</li>
								<li>
										<span>JMXServiceURL address = ...;  </span>
								</li>
								<li>
										<span>  </span>
								</li>
								<li>
										<span>
												<span class="comment">// The JMXAuthenticator implementation</span>
												<span>  </span>
										</span>
								</li>
								<li>
										<span>JMXAuthenticator authenticator = ...;  </span>
								</li>
								<li>
										<span>  </span>
								</li>
								<li>
										<span>
												<span class="comment">// The environment map</span>
												<span>  </span>
										</span>
								</li>
								<li>
										<span>Map environment = <span class="keyword">new</span><span> HashMap();  </span></span>
								</li>
								<li>
										<span>environment.put(JMXConnectorServer.AUTHENTICATOR, authenticator);  </span>
								</li>
								<li>
										<span>  </span>
								</li>
								<li>
										<span>
												<span class="comment">// The MBeanServer to which the JMXConnectorServer will be attached to</span>
												<span>  </span>
										</span>
								</li>
								<li>
										<span>MBeanServer server = MBeanServerFactory.createMBeanServer();  </span>
								</li>
								<li>
										<span>  </span>
								</li>
								<li>
										<span>
												<span class="comment">// Create the JMXCconnectorServer</span>
												<span>  </span>
										</span>
								</li>
								<li>
										<span>JMXConnectorServer cntorServer = JMXConnectorServerFactory.newJMXConnectorServer(address, environment, server);  </span>
								</li>
								<li>
										<span>  </span>
								</li>
								<li>
										<span>
												<span class="comment">// Start the JMXConnectorServer</span>
												<span>  </span>
										</span>
								</li>
								<li>
										<span>cntorServer.start();  </span>
								</li>
						</ol>
				</div>
				<p>    以下是在JMXConnector中使用JMXAuthenticator的例子：</p>
				<div class="dp-highlighter">
						<div class="bar">
								<div class="tools">Java代码 </div>
						</div>
						<ol class="dp-j" start="1">
								<li>
										<span>
												<span class="comment">// The address of the connector server</span>
												<span>  </span>
										</span>
								</li>
								<li>
										<span>JMXServiceURL address = ...;  </span>
								</li>
								<li>
										<span>  </span>
								</li>
								<li>
										<span>
												<span class="comment">// Create the JMXCconnectorServer</span>
												<span>  </span>
										</span>
								</li>
								<li>
										<span>JMXConnector cntor = JMXConnectorFactory.newJMXConnector(address, <span class="keyword">null</span><span>);  </span></span>
								</li>
								<li>
										<span>  </span>
								</li>
								<li>
										<span>
												<span class="comment">// The credentials</span>
												<span>  </span>
										</span>
								</li>
								<li>
										<span>Object credentials = ...;  </span>
								</li>
								<li>
										<span>  </span>
								</li>
								<li>
										<span>
												<span class="comment">// The connection environment map</span>
												<span>  </span>
										</span>
								</li>
								<li>
										<span>Map environment = <span class="keyword">new</span><span> HashMap();  </span></span>
								</li>
								<li>
										<span>environment.put(JMXConnector.CREDENTIALS, credentials);  </span>
								</li>
								<li>
										<span>  </span>
								</li>
								<li>
										<span>
												<span class="comment">// Connect and invoke an operation on the remote MBeanServer</span>
												<span>  </span>
										</span>
								</li>
								<li>
										<span>
												<span class="keyword">try</span>
												<span>  </span>
										</span>
								</li>
								<li>
										<span>{  </span>
								</li>
								<li>
										<span>   cntor.connect(environment);  </span>
								</li>
								<li>
										<span>}  </span>
								</li>
								<li>
										<span>
												<span class="keyword">catch</span>
												<span> (SecurityException x)  </span>
										</span>
								</li>
								<li>
										<span>{  </span>
								</li>
								<li>
										<span>   <span class="comment">// Uh-oh ! Bad credentials !</span><span>  </span></span>
								</li>
								<li>
										<span>   <span class="keyword">throw</span><span> x;  </span></span>
								</li>
								<li>
										<span>}  </span>
								</li>
								<li>
										<span>  </span>
								</li>
								<li>
										<span>
												<span class="comment">// Obtain a stub for the remote MBeanServer</span>
												<span>  </span>
										</span>
								</li>
								<li>
										<span>MBeanServerConnection mbsc = cntor.getMBeanServerConnection();  </span>
								</li>
								<li>
										<span>  </span>
								</li>
								<li>
										<span>
												<span class="comment">// Call the remote MBeanServer</span>
												<span>  </span>
										</span>
								</li>
								<li>
										<span>ObjectName delegate = ObjectName.getInstance(<span class="string">"JMImplementation:type=MBeanServerDelegate"</span><span>);  </span></span>
								</li>
								<li>
										<span>String id = mbsc.getAttribute(delegate, <span class="string">"MBeanServerId"</span><span>);  </span></span>
								</li>
						</ol>
				</div>
				<p>    当调用从JMXConnector 得到的MBeanServerConnection 
接口上的方法时，最终发生在远程MBeanServer的调用会以认证后的Subject 
身份执行。如果使用SecurityManager，那么还可以为不同的Subject指定不同的权限。</p>
		</div>
<img src ="http://www.blogjava.net/libin2722/aggbug/330634.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/libin2722/" target="_blank">礼物</a> 2010-09-01 22:34 <a href="http://www.blogjava.net/libin2722/articles/330634.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Spring JMS</title><link>http://www.blogjava.net/libin2722/articles/330632.html</link><dc:creator>礼物</dc:creator><author>礼物</author><pubDate>Wed, 01 Sep 2010 14:33:00 GMT</pubDate><guid>http://www.blogjava.net/libin2722/articles/330632.html</guid><wfw:comment>http://www.blogjava.net/libin2722/comments/330632.html</wfw:comment><comments>http://www.blogjava.net/libin2722/articles/330632.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/libin2722/comments/commentRss/330632.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/libin2722/services/trackbacks/330632.html</trackback:ping><description><![CDATA[
		<div class="blog_content">
				<p>
						<strong>1 DestinationResolver</strong>
						<br />
    DestinationResolver接口的作用是将指定的目的地名解析为目的地实例。其定义如下：</p>
				<div class="dp-highlighter">
						<div class="bar">
								<div class="tools">Java代码 </div>
						</div>
						<ol class="dp-j" start="1">
								<li>
										<span>
												<span class="keyword">public</span>
												<span> </span>
												<span class="keyword">interface</span>
												<span> DestinationResolver {  </span>
										</span>
								</li>
								<li>
										<span>    Destination resolveDestinationName(Session session, String destinationName,   </span>
								</li>
								<li>
										<span>        <span class="keyword">boolean</span><span> pubSubDomain) </span><span class="keyword">throws</span><span> JMSException;  </span></span>
								</li>
								<li>
										<span>}  </span>
								</li>
						</ol>
				</div>
				<p>    参数pubSubDomain用于指定是使用“发布/订阅”模式（解析后的目的地是Topic），还是使用“点对点”模式（解析后的目的地是Queue）。</p>
				<p> </p>
				<p>    CachingDestinationResolver接口继承了DestinationResolver，增加了缓存的功能，其接口定义如下：</p>
				<div class="dp-highlighter">
						<div class="bar">
								<div class="tools">Java代码 </div>
						</div>
						<ol class="dp-j" start="1">
								<li>
										<span>
												<span class="keyword">public</span>
												<span> </span>
												<span class="keyword">interface</span>
												<span> CachingDestinationResolver </span>
												<span class="keyword">extends</span>
												<span> DestinationResolver {  </span>
										</span>
								</li>
								<li>
										<span>    <span class="keyword">void</span><span> removeFromCache(String destinationName);  </span></span>
								</li>
								<li>
										<span>    <span class="keyword">void</span><span> clearCache();  </span></span>
								</li>
								<li>
										<span>}  </span>
								</li>
						</ol>
				</div>
				<p>    在目的地失效的时候，removeFromCache方法会被调用；在JMS provider失效的时候，clearCache方法会被调用。<br /><br /><strong>1.1 DynamicDestinationResolver</strong><br />
    DynamicDestinationResolver实现了DestinationResolver接口。根据指定的目的地名，DynamicDestinationResolver会动态创建目的地实例。针对JMS1.1规范，它采用如下方法创建目的地：</p>
				<div class="dp-highlighter">
						<div class="bar">
								<div class="tools">Java代码 </div>
						</div>
						<ol class="dp-j" start="1">
								<li>
										<span>
												<span>session.createTopic(topicName)  </span>
										</span>
								</li>
								<li>
										<span>session.createQueue(queueName);  </span>
								</li>
						</ol>
				</div>
				<p>
						<br />
						<strong>1.2 JndiDestinationResolver</strong>
						<br />
    JndiDestinationResolver继承自JndiLocatorSupport， 
同时实现了CachingDestinationResolver接口。如果在JMS 
provider中配置了静态目的地，那么JndiDestinationResolver通过JNDI查找的方式获得目的地实例。</p>
				<p>
						<br />
    
JndiDestinationResolver的fallbackToDynamicDestination属性用于指定在JNDI查找失败后，是否使
用动态目的地，默认值是false。JndiDestinationResolver的cache属性用于指定是否对目的地实例进行缓存，默认值是
true。</p>
				<p> </p>
				<p>
						<strong>1.3 BeanFactoryDestinationResolver</strong>
						<br />
    BeanFactoryDestinationResolver实现了DestinationResolver接口和BeanFactoryAware接口。它会根据指定的目的地名从BeanFactory中查找目的地实例。以下是相关的代码：</p>
				<div class="dp-highlighter">
						<div class="bar">
								<div class="tools">Java代码 </div>
						</div>
						<ol class="dp-j" start="1">
								<li>
										<span>
												<span class="keyword">public</span>
												<span> Destination resolveDestinationName(Session session, String destinationName,   </span>
										</span>
								</li>
								<li>
										<span>
												<span class="keyword">boolean</span>
												<span> pubSubDomain) </span>
												<span class="keyword">throws</span>
												<span> JMSException {  </span>
										</span>
								</li>
								<li>
										<span>    Assert.state(<span class="keyword">this</span><span>.beanFactory != </span><span class="keyword">null</span><span>, </span><span class="string">"BeanFactory is required"</span><span>);  </span></span>
								</li>
								<li>
										<span>    <span class="keyword">try</span><span> {  </span></span>
								</li>
								<li>
										<span>        <span class="keyword">return</span><span> (Destination) </span><span class="keyword">this</span><span>.beanFactory.getBean(destinationName, Destination.</span><span class="keyword">class</span><span>);  </span></span>
								</li>
								<li>
										<span>    }  </span>
								</li>
								<li>
										<span>    <span class="keyword">catch</span><span> (BeansException ex) {  </span></span>
								</li>
								<li>
										<span>        <span class="keyword">throw</span><span> </span><span class="keyword">new</span><span> DestinationResolutionException(  </span></span>
								</li>
								<li>
										<span>            <span class="string">"Failed to look up Destinaton bean with name '"</span><span> + destinationName + </span><span class="string">"'"</span><span>, ex);  </span></span>
								</li>
								<li>
										<span>    }  </span>
								</li>
								<li>
										<span>}  </span>
								</li>
						</ol>
				</div>
				<p> </p>
				<p>
						<strong>2 JmsAccessor</strong>
						<br />
    
抽象类JmsAccessor是JmsTemplate、SimpleMessageListenerContainer和
DefaultMessageListenerContainer等concrete 
class的基类。JmsAccessor定义了如下几个用于访问JMS服务的共通属性。</p>
				<div class="dp-highlighter">
						<div class="bar">
								<div class="tools">Java代码 </div>
						</div>
						<ol class="dp-j" start="1">
								<li>
										<span>
												<span class="keyword">private</span>
												<span> ConnectionFactory connectionFactory;  </span>
										</span>
								</li>
								<li>
										<span>
												<span class="keyword">private</span>
												<span> </span>
												<span class="keyword">boolean</span>
												<span> sessionTransacted = </span>
												<span class="keyword">false</span>
												<span>;  </span>
										</span>
								</li>
								<li>
										<span>
												<span class="keyword">private</span>
												<span> </span>
												<span class="keyword">int</span>
												<span> sessionAcknowledgeMode = Session.AUTO_ACKNOWLEDGE;  </span>
										</span>
								</li>
						</ol>
				</div>
				<p>
						<br />
    JmsAccessor提供了创建Connection和Session的方法，如下：</p>
				<div class="dp-highlighter">
						<div class="bar">
								<div class="tools">Java代码 </div>
						</div>
						<ol class="dp-j" start="1">
								<li>
										<span>
												<span class="keyword">protected</span>
												<span> Connection createConnection() </span>
												<span class="keyword">throws</span>
												<span> JMSException {  </span>
										</span>
								</li>
								<li>
										<span>    <span class="keyword">return</span><span> getConnectionFactory().createConnection();  </span></span>
								</li>
								<li>
										<span>}  </span>
								</li>
								<li>
										<span>  </span>
								</li>
								<li>
										<span>
												<span class="keyword">protected</span>
												<span> Session createSession(Connection con) </span>
												<span class="keyword">throws</span>
												<span> JMSException {  </span>
										</span>
								</li>
								<li>
										<span>    <span class="keyword">return</span><span> con.createSession(isSessionTransacted(), getSessionAcknowledgeMode());  </span></span>
								</li>
								<li>
										<span>}  </span>
								</li>
						</ol>
				</div>
				<p> <br /><strong>2.1 JmsDestinationAccessor</strong><br />
    
抽象类JmsDestinationAccessor继承自JmsAccessor，增加了destinationResolver和
pubSubDomain属性。destinationResolver的默认值是DynamicDestinationResolver的实例，也就是
说默认采用动态目的地解析的方式；pubSubDomain用于指定是使用“发布/订阅”模式还是使用“点对点”模式，默认值是false。<br /><br />
    JmsDestinationAccessor提供了用于解析目的地的方法，如下：</p>
				<div class="dp-highlighter">
						<div class="bar">
								<div class="tools">Java代码 </div>
						</div>
						<ol class="dp-j" start="1">
								<li>
										<span>
												<span class="keyword">protected</span>
												<span> Destination resolveDestinationName(Session session, String destinationName)   </span>
										</span>
								</li>
								<li>
										<span>
												<span class="keyword">throws</span>
												<span> JMSException {  </span>
										</span>
								</li>
								<li>
										<span>    <span class="keyword">return</span><span> getDestinationResolver().resolveDestinationName(session, destinationName,   </span></span>
								</li>
								<li>
										<span>        isPubSubDomain());  </span>
								</li>
								<li>
										<span>}  </span>
								</li>
						</ol>
				</div>
				<p>
						<br />
						<strong>2.2 AbstractJmsListeningContainer</strong>
						<br />
    AbstractJmsListeningContainer继承自JmsDestinationAccessor，作为所有Message 
Listener Container的公共基类。它主要提供了JMS 
connection的生命周期管理的功能，但是没有对消息接收的方式（主动接收方式或者异步接收方式）等做任何假定。该类主要的属性如下：</p>
				<div class="dp-highlighter">
						<div class="bar">
								<div class="tools">Java代码 </div>
						</div>
						<ol class="dp-j" start="1">
								<li>
										<span>
												<span class="keyword">private</span>
												<span> String clientId;  </span>
										</span>
								</li>
								<li>
										<span>
												<span class="keyword">private</span>
												<span> Connection sharedConnection;  </span>
										</span>
								</li>
						</ol>
				</div>
				<p>    clientId通常用于持久订阅；sharedConnection保存了被共享的JMS connection。</p>
				<p> </p>
				<p>    该类定义了如下的抽象方法，以便子类可以决定是否使用共享的JMS connection。</p>
				<div class="dp-highlighter">
						<div class="bar">
								<div class="tools">Java代码 </div>
						</div>
						<ol class="dp-j" start="1">
								<li>
										<span>
												<span class="keyword">protected</span>
												<span> </span>
												<span class="keyword">abstract</span>
												<span> </span>
												<span class="keyword">boolean</span>
												<span> sharedConnectionEnabled();  </span>
										</span>
								</li>
						</ol>
				</div>
				<p> </p>
				<p>
						<strong>2.3 AbstractMessageListenerContainer</strong>
						<br />
    AbstractMessageListenerContainer继承自AbstractJmsListeningContainer，也是作为所有Message Listener Container的公共基类。该类主要的属性如下：</p>
				<div class="dp-highlighter">
						<div class="bar">
								<div class="tools">Java代码 </div>
						</div>
						<ol class="dp-j" start="1">
								<li>
										<span>
												<span class="keyword">private</span>
												<span> </span>
												<span class="keyword">volatile</span>
												<span> Object destination;  </span>
										</span>
								</li>
								<li>
										<span>
												<span class="keyword">private</span>
												<span> </span>
												<span class="keyword">volatile</span>
												<span> Object messageListener;  </span>
										</span>
								</li>
								<li>
										<span>
												<span class="keyword">private</span>
												<span> </span>
												<span class="keyword">boolean</span>
												<span> exposeListenerSession = </span>
												<span class="keyword">true</span>
												<span>;  </span>
										</span>
								</li>
						</ol>
				</div>
				<p>    destination用于指定接收消息的目的地。<br />
    
messageListener用于指定处理消息的listener。对于messageListener，它既可以是符合JMS规范的
javax.jms.MessageListener，也可以是Spring特有的
org.springframework.jms.listener.SessionAwareMessageListener。
SessionAwareMessageListener的定义如下：</p>
				<div class="dp-highlighter">
						<div class="bar">
								<div class="tools">Java代码 </div>
						</div>
						<ol class="dp-j" start="1">
								<li>
										<span>
												<span class="keyword">public</span>
												<span> </span>
												<span class="keyword">interface</span>
												<span> SessionAwareMessageListener {  </span>
										</span>
								</li>
								<li>
										<span>    <span class="keyword">void</span><span> onMessage(Message message, Session session) </span><span class="keyword">throws</span><span> JMSException;  </span></span>
								</li>
								<li>
										<span>}  </span>
								</li>
						</ol>
				</div>
				<p>    跟javax.jms.MessageListener相比，这个接口的onMessage方法增加了一个Session 类型的参数，可以通过这个session发送回复消息（reply message）。</p>
				<p>
						<br />
    如果使用了SessionAwareMessageListener 类型的message 
listener，那么exposeListenerSession参数指定了传入onMessage方法的session参数是否是创建了
MessageConsumer的session，默认值是true。如果是false，那么
AbstractMessageListenerContainer会在connection上新建一个session，并传入onMessage方法。<br /><br /><strong>2.4 AbstractPollingMessageListenerContainer</strong><br />
    AbstractPollingMessageListenerContainer继承自AbstractMessageListenerContainer，它提供了对于主动接收消息(polling)的支持，以及支持外部的事务管理。</p>
				<div class="dp-highlighter">
						<div class="bar">
								<div class="tools">Java代码 </div>
						</div>
						<ol class="dp-j" start="1">
								<li>
										<span>
												<span class="keyword">private</span>
												<span> </span>
												<span class="keyword">boolean</span>
												<span> pubSubNoLocal = </span>
												<span class="keyword">false</span>
												<span>;  </span>
										</span>
								</li>
								<li>
										<span>
												<span class="keyword">private</span>
												<span> </span>
												<span class="keyword">long</span>
												<span> receiveTimeout = DEFAULT_RECEIVE_TIMEOUT;  </span>
										</span>
								</li>
								<li>
										<span>
												<span class="keyword">private</span>
												<span> PlatformTransactionManager transactionManager;  </span>
										</span>
								</li>
						</ol>
				</div>
				<p>    如果使用“发布/订阅”模式，那么pubSubNoLocal 属性指定通过某个连接发送到某个Topic的消息，是否应该被投递回这个连接。</p>
				<p>
						<br />
    receiveTimeout属性用于指定调用MessageConsumer的receive方法时的超时时间，默认值是1秒。需要注意的是，这个值应该比transactionManager 中指定的事务超时时间略小。</p>
				<p>
						<br />
    
通常情况下，应该为transactionManager设置一个
org.springframework.transaction.jta.JtaTransactionManager的实例，此外也要设置一个支持
XA的ConnectionFactory。需要注意的是，XA 事务对性能有较大的影响。<br />
    如果只是希望使用local JMS 
transaction，那么只要设置sessionTransacted为true或者使用JmsTransactionManager即可。实际上，
如果设置了非JTA的transactionManager，那么sessionTransacted属性会自动被设置成true。<br />
    由于local JMS transaction无法同其它local transaction（例如local database 
transaction）进行协调，因此客户端程序可能需要对重发的消息进行检查。JMS规范要求：JMS 
provider应该将重发消息的JMSRedelivered属性设置为true。<br /><br /><strong>2.5 SimpleMessageListenerContainer</strong><br />
    
SimpleMessageListenerContainer继承自AbstractMessageListenerContainer，使用异步方式
接收消息（也就是通过MessageConsumer上注册MessageListener的方式接收消息）。该类主要的属性如下：</p>
				<div class="dp-highlighter">
						<div class="bar">
								<div class="tools">Java代码 </div>
						</div>
						<ol class="dp-j" start="1">
								<li>
										<span>
												<span class="keyword">private</span>
												<span> </span>
												<span class="keyword">boolean</span>
												<span> pubSubNoLocal = </span>
												<span class="keyword">false</span>
												<span>;  </span>
										</span>
								</li>
								<li>
										<span>
												<span class="keyword">private</span>
												<span> </span>
												<span class="keyword">int</span>
												<span> concurrentConsumers = </span>
												<span class="number">1</span>
												<span>;  </span>
										</span>
								</li>
								<li>
										<span>
												<span class="keyword">private</span>
												<span> Set sessions;  </span>
										</span>
								</li>
								<li>
										<span>
												<span class="keyword">private</span>
												<span> Set consumers;  </span>
										</span>
								</li>
								<li>
										<span>
												<span class="keyword">private</span>
												<span> TaskExecutor taskExecutor;  </span>
										</span>
								</li>
						</ol>
				</div>
				<p>    如果使用“发布/订阅”模式，那么pubSubNoLocal 属性指定通过某个连接发送到某个Topic的消息，是否应该被投递回这个连接。</p>
				<p> </p>
				<p>
    
SimpleMessageListenerContainer允许创建多个Session和MessageConsumer来接收消息。具体的个数由
concurrentConsumers属性指定。需要注意的是，应该只是在Destination为Queue的时候才使用多个
MessageConsumer（Queue中的一个消息只能被一个Consumer接收），虽然使用多个MessageConsumer会提高消息处理
的性能，但是消息处理的顺序却得不到保证：消息被接收的顺序仍然是消息发送时的顺序，但是由于消息可能会被并发处理，因此消息处理的顺序可能和消息发送的
顺序不同。此外，不应该在Destination为Topic的时候使用多个MessageConsumer，这是因为多个
MessageConsumer会接收到同样的消息。</p>
				<p>    SimpleMessageListenerContainer创建的Session和MessageConsumer分别保存在sessions和consumers属性中。</p>
				<p>
						<br />
    
taskExecutor属性的默认值是null，也就是说，对MessageListener（或者
SessionAwareMessageListener）的回调是在MessageConsumer的内部线程中执行。如果指定了
taskExecutor，那么回调是在TaskExecutor内部的线程中执行。以下是相关的代码：</p>
				<div class="dp-highlighter">
						<div class="bar">
								<div class="tools">Java代码 </div>
						</div>
						<ol class="dp-j" start="1">
								<li>
										<span>
												<span class="keyword">protected</span>
												<span> MessageConsumer createListenerConsumer(</span>
												<span class="keyword">final</span>
												<span> Session session)   </span>
										</span>
								</li>
								<li>
										<span>
												<span class="keyword">throws</span>
												<span> JMSException {  </span>
										</span>
								</li>
								<li>
										<span>    Destination destination = getDestination();  </span>
								</li>
								<li>
										<span>    <span class="keyword">if</span><span> (destination == </span><span class="keyword">null</span><span>) {  </span></span>
								</li>
								<li>
										<span>        destination = resolveDestinationName(session, getDestinationName());  </span>
								</li>
								<li>
										<span>    }  </span>
								</li>
								<li>
										<span>    MessageConsumer consumer = createConsumer(session, destination);  </span>
								</li>
								<li>
										<span>  </span>
								</li>
								<li>
										<span>    <span class="keyword">if</span><span> (</span><span class="keyword">this</span><span>.taskExecutor != </span><span class="keyword">null</span><span>) {  </span></span>
								</li>
								<li>
										<span>        consumer.setMessageListener(<span class="keyword">new</span><span> MessageListener() {  </span></span>
								</li>
								<li>
										<span>            <span class="keyword">public</span><span> </span><span class="keyword">void</span><span> onMessage(</span><span class="keyword">final</span><span> Message message) {  </span></span>
								</li>
								<li>
										<span>                taskExecutor.execute(<span class="keyword">new</span><span> Runnable() {  </span></span>
								</li>
								<li>
										<span>                    <span class="keyword">public</span><span> </span><span class="keyword">void</span><span> run() {  </span></span>
								</li>
								<li>
										<span>                        processMessage(message, session);  </span>
								</li>
								<li>
										<span>                    }  </span>
								</li>
								<li>
										<span>                });  </span>
								</li>
								<li>
										<span>            }  </span>
								</li>
								<li>
										<span>        });  </span>
								</li>
								<li>
										<span>    }  </span>
								</li>
								<li>
										<span>    <span class="keyword">else</span><span> {  </span></span>
								</li>
								<li>
										<span>        consumer.setMessageListener(<span class="keyword">new</span><span> MessageListener() {  </span></span>
								</li>
								<li>
										<span>            <span class="keyword">public</span><span> </span><span class="keyword">void</span><span> onMessage(Message message) {  </span></span>
								</li>
								<li>
										<span>                processMessage(message, session);  </span>
								</li>
								<li>
										<span>            }  </span>
								</li>
								<li>
										<span>        });  </span>
								</li>
								<li>
										<span>    }  </span>
								</li>
								<li>
										<span>  </span>
								</li>
								<li>
										<span>    <span class="keyword">return</span><span> consumer;  </span></span>
								</li>
								<li>
										<span>}  </span>
								</li>
						</ol>
				</div>
				<p>    
需要注意的是，如果指定了taskExecutor，那么消息在被taskExecutor内部的线程处理前，可能已经被确认过了（外层的
onMessage方法可能已经执行结束了）。因此如果使用事务Session或者Session.CLIENT_ACKNOWLEDGE类型的确认模
式，那么可能会导致问题。</p>
				<p> </p>
				<p>    
该类的sharedConnectionEnabled方法（在AbstractJmsListeningContainer中定义）总是返回true，
因此SimpleMessageListenerContainer会使用共享的JMS connection。<br /><br /><strong>2.6 DefaultMessageListenerContainer</strong><br />
    
DefaultMessageListenerContainer继承自
AbstractPollingMessageListenerContainer，主要使用同步的方式接收消息（也就是通过循环调用
MessageConsumer.receive的方式接收消息）。该类主要的属性如下：</p>
				<div class="dp-highlighter">
						<div class="bar">
								<div class="tools">Java代码 </div>
						</div>
						<ol class="dp-j" start="1">
								<li>
										<span>
												<span class="keyword">private</span>
												<span> </span>
												<span class="keyword">int</span>
												<span> concurrentConsumers = </span>
												<span class="number">1</span>
												<span>;  </span>
										</span>
								</li>
								<li>
										<span>
												<span class="keyword">private</span>
												<span> </span>
												<span class="keyword">int</span>
												<span> maxConcurrentConsumers = </span>
												<span class="number">1</span>
												<span>;  </span>
										</span>
								</li>
								<li>
										<span>
												<span class="keyword">private</span>
												<span> </span>
												<span class="keyword">int</span>
												<span> maxMessagesPerTask = Integer.MIN_VALUE;  </span>
										</span>
								</li>
								<li>
										<span>
												<span class="keyword">private</span>
												<span> </span>
												<span class="keyword">int</span>
												<span> idleTaskExecutionLimit = </span>
												<span class="number">1</span>
												<span>;  </span>
										</span>
								</li>
								<li>
										<span>
												<span class="keyword">private</span>
												<span> </span>
												<span class="keyword">final</span>
												<span> Set scheduledInvokers = </span>
												<span class="keyword">new</span>
												<span> HashSet();  </span>
										</span>
								</li>
								<li>
										<span>
												<span class="keyword">private</span>
												<span> TaskExecutor taskExecutor;  </span>
										</span>
								</li>
								<li>
										<span>
												<span class="keyword">private</span>
												<span> </span>
												<span class="keyword">int</span>
												<span> cacheLevel = CACHE_AUTO;  </span>
										</span>
								</li>
						</ol>
				</div>
				<p>    
跟SimpleMessageListenerContainer一样，DefaultMessageListenerContainer也支持创建多个
Session和MessageConsumer来接收消息。跟SimpleMessageListenerContainer不同的
是，DefaultMessageListenerContainer创建了concurrentConsumers所指定个数的
AsyncMessageListenerInvoker（实现了SchedulingAwareRunnable接口），并交给
taskExecutor运行。</p>
				<p>
						<br />
    
maxMessagesPerTask属性的默认值是Integer.MIN_VALUE，但是如果设置的taskExecutor（默认值是
SimpleAsyncTaskExecutor）实现了SchedulingTaskExecutor接口并且其
prefersShortLivedTasks方法返回true（也就是说该TaskExecutor倾向于短期任务），那么
maxMessagesPerTask属性会自动被设置为10。<br />
    
如果maxMessagesPerTask属性的值小于0，那么AsyncMessageListenerInvoker.run方法会在循环中反复尝试
接收消息，并在接收到消息后调用MessageListener（或者SessionAwareMessageListener）；如果
maxMessagesPerTask属性的值不小于0，那么AsyncMessageListenerInvoker.run方法里最多会尝试接收消息
maxMessagesPerTask次，每次接收消息的超时时间由其父类
AbstractPollingMessageListenerContainer的receiveTimeout属性指定。如果在这些尝试中都没有接收
到消息，那么AsyncMessageListenerInvoker的idleTaskExecutionCount属性会被累加。在run方法执行完
毕前会对idleTaskExecutionCount进行检查，如果该值超过了
DefaultMessageListenerContainer.idleTaskExecutionLimit（默认值1），那么这个
AsyncMessageListenerInvoker可能会被销毁。</p>
				<p>
						<br />
    
所有AsyncMessageListenerInvoker实例都保存在scheduledInvokers中，实例的个数可以在
concurrentConsumers和maxConcurrentConsumers之间浮动。跟
SimpleMessageListenerContainer一样，应该只是在Destination为Queue的时候才使用多个
AsyncMessageListenerInvoker实例。</p>
				<p> </p>
				<p>    cacheLevel属性用于指定是否对JMS资源进行缓存，可选的值是CACHE_NONE = 0、CACHE_CONNECTION
 = 1、CACHE_SESSION = 2、CACHE_CONSUMER = 3和CACHE_AUTO = 
4。默认情况下，如果transactionManager属性不为null，那么cacheLevel被自动设置为CACHE_NONE（不进行缓
存），否则cacheLevel被自动设置为CACHE_CONSUMER。</p>
				<p>
						<br />
    如果cacheLevel属性值大于等于CACHE_CONNECTION，那么sharedConnectionEnabled方法（在AbstractJmsListeningContainer中定义）返回true，也就是说使用共享的JMS连接。</p>
				<p> </p>
				<p> </p>
				<p>
						<strong>3 SingleConnectionFactory</strong>
						<br />
    
SingleConnectionFactory实现了ConnectionFactory接口，其createConnection方法总是返回相同的
Connection。可以在SingleConnectionFactory的构造函数中传入Connection对象或者
ConnectionFactory对象，用来创建被代理的连接对象。
SingleConnectionFactory.createConnection方法返回的连接是个代理，它忽略了对stop和close方法的调用
（连接会在SingleConnectionFactory.destroy方法中关闭）。</p>
				<p>
						<br />
    SingleConnectionFactory的reconnectOnException属性用来指定是否在连接抛出JMSException的时候，对连接进行重置，重置后如果再调用createConnection方法，那么会返回一个新的连接。</p>
				<p>
						<br />
    
需要注意的是，AbstractJmsListeningContainer类的抽象方法sharedConnectionEnabled指定了是否在
message listener container内部使用共享的JMS连接。因此通常情况下不需要为单独的message listener 
container设置SingleConnectionFactory（及其子类）；如果希望在不同的message listener 
container之间共享JMS连接，那么可以考虑使用SingleConnectionFactory。<br /><br /><strong>3.1 CachingConnectionFactory</strong><br />
    CachingConnectionFactory继承自SingleConnectionFactory，增加了对Session和MessageProducer缓存的功能。该类主要的属性如下：</p>
				<div class="dp-highlighter">
						<div class="bar">
								<div class="tools">Java代码 </div>
						</div>
						<ol class="dp-j" start="1">
								<li>
										<span>
												<span class="keyword">private</span>
												<span> </span>
												<span class="keyword">int</span>
												<span> sessionCacheSize = </span>
												<span class="number">1</span>
												<span>;  </span>
										</span>
								</li>
								<li>
										<span>
												<span class="keyword">private</span>
												<span> </span>
												<span class="keyword">boolean</span>
												<span> cacheProducers = </span>
												<span class="keyword">true</span>
												<span>;  </span>
										</span>
								</li>
						</ol>
				</div>
				<p>    sessionCacheSize属性指定了被缓存的Session实例的个数（默认值是1），也就是说，如果同时请求的Session个数大于sessionCacheSize，那么这些Session不会被缓存，而是正常的被创建和销毁。</p>
				<p>
						<br />
    cacheProducers属性指定了是否对MessageProducer进行缓存，默认值是true。</p>
		</div>
<img src ="http://www.blogjava.net/libin2722/aggbug/330632.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/libin2722/" target="_blank">礼物</a> 2010-09-01 22:33 <a href="http://www.blogjava.net/libin2722/articles/330632.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>ActiveMQ5.0实战三:使用Spring发送,消费topic和queue消息</title><link>http://www.blogjava.net/libin2722/articles/249400.html</link><dc:creator>礼物</dc:creator><author>礼物</author><pubDate>Wed, 31 Dec 2008 14:10:00 GMT</pubDate><guid>http://www.blogjava.net/libin2722/articles/249400.html</guid><wfw:comment>http://www.blogjava.net/libin2722/comments/249400.html</wfw:comment><comments>http://www.blogjava.net/libin2722/articles/249400.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/libin2722/comments/commentRss/249400.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/libin2722/services/trackbacks/249400.html</trackback:ping><description><![CDATA[<h3>简介</h3>
<p>实战一 , 实战二介绍了ActiveMQ的基本概念和配置方式.</p>
<p>本篇将通过一个实例介绍使用spring发送,消费topic, queue类型消息的方法. 不懂topic和queue的google 之.</p>
<p>&nbsp;</p>
<p><a href="http://andyao.javaeye.com/upload/picture/pic/20785/485ba4ca-70db-3a46-a5c8-1cd3d9b81f65.gif" target="_blank"><img height="209" alt="" src="http://andyao.javaeye.com/upload/picture/pic/20785/485ba4ca-70db-3a46-a5c8-1cd3d9b81f65.gif" width="387" _counted="undefined" /> </a></p>
<p>如图示, TOPIC和QUEUE分别代表一个topic和一个queue消息通道. </p>
<ol>
    <li>TopicMessageProducer向topic发送消息, TopicConsumerA和TopicConsumerB则从topic消费消息.
    <li>QueueMessageProducer向Queue发送消息, QueueConsumer从Queue中消费消息 </li>
</ol>
<h3>Spring整合JMS</h3>
<p>就像对orm, web的支持一样, spring同样支持jms, 为整合jms到已有的项目提供了很多便利的方法. 本篇主要讲实战, 是所以先从配置开始, spring配置jms基本上需要8个部分.</p>
<ol>
    <li>ConnectionFactory. 和jms服务器的连接, 可以是外部的jms server, 也可以使用embedded ActiveMQ Broker.
    <li>Destination. 有topic和queue两种方式.
    <li>JmsTemplate. spring提供的jms模板.
    <li>MessageConverter. 消息转换器.
    <li>MessageProducer. 消息生产者.
    <li>MessageConsumer. 消息消费者.
    <li>MessageListener. 消息监听器
    <li>MessageListenerContainer. 消息监听容器 </li>
</ol>
<p>下面以实例的方式介绍上面8个部分.</p>
<h4>1. ConnectionFactory</h4>
<div class="dp-highlighter">
<div class="bar">
<div class="tools">Xml代码 <a title="复制代码" onclick="dp.sh.Toolbar.Command('CopyToClipboard',this);return false;" href="http://andyao.javaeye.com/blog/234101#"><img alt="复制代码" src="http://andyao.javaeye.com/images/icon_copy.gif" _counted="undefined" /></a></div>
</div>
<ol class="dp-xml">
    <li><span><span class="tag">&lt;</span><span class="tag-name">amq:connectionFactory</span><span>&nbsp;</span><span class="attribute">id</span><span>=</span><span class="attribute-value">"jmsConnectionFactory"</span><span>&nbsp;</span><span class="attribute">brokerURL</span><span>=</span><span class="attribute-value">"vm://localhost"</span><span>&nbsp;</span><span class="tag">/&gt;</span><span>&nbsp;&nbsp;</span></span></li>
</ol>
</div>
<pre class="xml" style="display: none" name="code">&lt;amq:connectionFactory id="jmsConnectionFactory" brokerURL="vm://localhost" /&gt;</pre>
<p>&nbsp;brokerURL是指要连接的activeMQ server的地址, activeMQ提供了多种brokerURL, 集体可参见文档.一般我们使用嵌套的ActiveMQ server. 配置如下, 这个配置使用消息的存储机制, 服务器重启也不会丢失消息.</p>
<div class="dp-highlighter">
<div class="bar">
<div class="tools">Xml代码 <a title="复制代码" onclick="dp.sh.Toolbar.Command('CopyToClipboard',this);return false;" href="http://andyao.javaeye.com/blog/234101#"><img alt="复制代码" src="http://andyao.javaeye.com/images/icon_copy.gif" _counted="undefined" /></a></div>
</div>
<ol class="dp-xml">
    <li><span><span class="comments">&lt;!--&nbsp;&nbsp;embedded&nbsp;ActiveMQ&nbsp;Broker&nbsp;--&gt;</span><span>&nbsp;&nbsp;</span></span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="tag">&lt;</span><span class="tag-name">amq:broker</span><span>&nbsp;</span><span class="attribute">useJmx</span><span>=</span><span class="attribute-value">"false"</span><span>&nbsp;</span><span class="attribute">persistent</span><span>=</span><span class="attribute-value">"true"</span><span class="tag">&gt;</span><span>&nbsp;&nbsp;</span></span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="tag">&lt;</span><span class="tag-name">amq:persistenceAdapter</span><span class="tag">&gt;</span><span>&nbsp;&nbsp;</span></span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="tag">&lt;</span><span class="tag-name">amq:amqPersistenceAdapter</span><span>&nbsp;</span><span class="attribute">directory</span><span>=</span><span class="attribute-value">"d:/amq"</span><span class="tag">/&gt;</span><span>&nbsp;&nbsp;</span></span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="tag">&lt;/</span><span class="tag-name">amq:persistenceAdapter</span><span class="tag">&gt;</span><span>&nbsp;&nbsp;</span></span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="tag">&lt;</span><span class="tag-name">amq:transportConnectors</span><span class="tag">&gt;</span><span>&nbsp;&nbsp;</span></span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="tag">&lt;</span><span class="tag-name">amq:transportConnector</span><span>&nbsp;</span><span class="attribute">uri</span><span>=</span><span class="attribute-value">"tcp://localhost:61616"</span><span>&nbsp;</span><span class="tag">/&gt;</span><span>&nbsp;&nbsp;</span></span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="tag">&lt;</span><span class="tag-name">amq:transportConnector</span><span>&nbsp;</span><span class="attribute">uri</span><span>=</span><span class="attribute-value">"vm://localhost:0"</span><span>&nbsp;</span><span class="tag">/&gt;</span><span>&nbsp;&nbsp;</span></span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="tag">&lt;/</span><span class="tag-name">amq:transportConnectors</span><span class="tag">&gt;</span><span>&nbsp;&nbsp;</span></span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="tag">&lt;/</span><span class="tag-name">amq:broker</span><span class="tag">&gt;</span><span>&nbsp;&nbsp;</span></span></li>
</ol>
</div>
<pre class="xml" style="display: none" name="code">&lt;!--  embedded ActiveMQ Broker --&gt;
&lt;amq:broker useJmx="false" persistent="true"&gt;
&lt;amq:persistenceAdapter&gt;
&lt;amq:amqPersistenceAdapter directory="d:/amq"/&gt;
&lt;/amq:persistenceAdapter&gt;
&lt;amq:transportConnectors&gt;
&lt;amq:transportConnector uri="tcp://localhost:61616" /&gt;
&lt;amq:transportConnector uri="vm://localhost:0" /&gt;
&lt;/amq:transportConnectors&gt;
&lt;/amq:broker&gt;</pre>
<h4>&nbsp;2. Destination</h4>
<p>&nbsp;在实例中我们使用了两种destination</p>
<div class="dp-highlighter">
<div class="bar">
<div class="tools">Xml代码 <a title="复制代码" onclick="dp.sh.Toolbar.Command('CopyToClipboard',this);return false;" href="http://andyao.javaeye.com/blog/234101#"><img alt="复制代码" src="http://andyao.javaeye.com/images/icon_copy.gif" _counted="undefined" /></a></div>
</div>
<ol class="dp-xml">
    <li><span><span class="comments">&lt;!--&nbsp;&nbsp;ActiveMQ&nbsp;destinations&nbsp;&nbsp;--&gt;</span><span>&nbsp;&nbsp;</span></span></li>
    <li><span class="comments">&lt;!--&nbsp;&nbsp;使用topic方式--&gt;</span><span>&nbsp;&nbsp;</span></span></li>
    <li><span class="tag">&lt;</span><span class="tag-name">amq:topic</span><span>&nbsp;</span><span class="attribute">name</span><span>=</span><span class="attribute-value">"TOPIC"</span><span>&nbsp;</span><span class="attribute">physicalName</span><span>=</span><span class="attribute-value">"JMS-TEST-TOPIC"</span><span>&nbsp;</span><span class="tag">/&gt;</span><span>&nbsp;&nbsp;</span></span></li>
    <li><span class="comments">&lt;!--&nbsp;&nbsp;使用Queue方式--&gt;</span><span>&nbsp;&nbsp;</span></span></li>
    <li><span class="tag">&lt;</span><span class="tag-name">amq:queue</span><span>&nbsp;</span><span class="attribute">name</span><span>=</span><span class="attribute-value">"QUEUE"</span><span>&nbsp;</span><span class="attribute">physicalName</span><span>=</span><span class="attribute-value">"JMS-TEST-QUEUE"</span><span>&nbsp;</span><span class="tag">/&gt;</span><span>&nbsp;&nbsp;</span></span></li>
</ol>
</div>
<pre class="xml" style="display: none" name="code">&lt;!--  ActiveMQ destinations  --&gt;
&lt;!--  使用topic方式--&gt;
&lt;amq:topic name="TOPIC" physicalName="JMS-TEST-TOPIC" /&gt;
&lt;!--  使用Queue方式--&gt;
&lt;amq:queue name="QUEUE" physicalName="JMS-TEST-QUEUE" /&gt;</pre>
<h4>&nbsp;3. JmsTemplate</h4>
<div class="dp-highlighter">
<div class="bar">
<div class="tools">Xml代码 <a title="复制代码" onclick="dp.sh.Toolbar.Command('CopyToClipboard',this);return false;" href="http://andyao.javaeye.com/blog/234101#"><img alt="复制代码" src="http://andyao.javaeye.com/images/icon_copy.gif" _counted="undefined" /></a></div>
</div>
<ol class="dp-xml">
    <li><span><span class="comments">&lt;!--&nbsp;&nbsp;Spring&nbsp;JmsTemplate&nbsp;config&nbsp;--&gt;</span><span>&nbsp;&nbsp;</span></span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="tag">&lt;</span><span class="tag-name">bean</span><span>&nbsp;</span><span class="attribute">id</span><span>=</span><span class="attribute-value">"jmsTemplate"</span><span>&nbsp;</span><span class="attribute">class</span><span>=</span><span class="attribute-value">"org.springframework.jms.core.JmsTemplate"</span><span class="tag">&gt;</span><span>&nbsp;&nbsp;</span></span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="tag">&lt;</span><span class="tag-name">property</span><span>&nbsp;</span><span class="attribute">name</span><span>=</span><span class="attribute-value">"connectionFactory"</span><span class="tag">&gt;</span><span>&nbsp;&nbsp;</span></span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="comments">&lt;!--&nbsp;&nbsp;lets&nbsp;wrap&nbsp;in&nbsp;a&nbsp;pool&nbsp;to&nbsp;avoid&nbsp;creating&nbsp;a&nbsp;connection&nbsp;per&nbsp;send&nbsp;--&gt;</span><span>&nbsp;&nbsp;</span></span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="tag">&lt;</span><span class="tag-name">bean</span><span>&nbsp;</span><span class="attribute">class</span><span>=</span><span class="attribute-value">"org.springframework.jms.connection.SingleConnectionFactory"</span><span class="tag">&gt;</span><span>&nbsp;&nbsp;</span></span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="tag">&lt;</span><span class="tag-name">property</span><span>&nbsp;</span><span class="attribute">name</span><span>=</span><span class="attribute-value">"targetConnectionFactory"</span><span>&nbsp;</span><span class="attribute">ref</span><span>=</span><span class="attribute-value">"jmsConnectionFactory"</span><span>&nbsp;</span><span class="tag">/&gt;</span><span>&nbsp;&nbsp;</span></span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="tag">&lt;/</span><span class="tag-name">bean</span><span class="tag">&gt;</span><span>&nbsp;&nbsp;</span></span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="tag">&lt;/</span><span class="tag-name">property</span><span class="tag">&gt;</span><span>&nbsp;&nbsp;</span></span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="comments">&lt;!--&nbsp;custom&nbsp;MessageConverter&nbsp;--&gt;</span><span>&nbsp;&nbsp;</span></span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="tag">&lt;</span><span class="tag-name">property</span><span>&nbsp;</span><span class="attribute">name</span><span>=</span><span class="attribute-value">"messageConverter"</span><span>&nbsp;</span><span class="attribute">ref</span><span>=</span><span class="attribute-value">"defaultMessageConverter"</span><span>&nbsp;</span><span class="tag">/&gt;</span><span>&nbsp;&nbsp;</span></span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="tag">&lt;/</span><span class="tag-name">bean</span><span class="tag">&gt;</span><span>&nbsp;&nbsp;</span></span></li>
</ol>
</div>
<pre class="xml" style="display: none" name="code">&lt;!--  Spring JmsTemplate config --&gt;
&lt;bean id="jmsTemplate" class="org.springframework.jms.core.JmsTemplate"&gt;
&lt;property name="connectionFactory"&gt;
&lt;!--  lets wrap in a pool to avoid creating a connection per send --&gt;
&lt;bean class="org.springframework.jms.connection.SingleConnectionFactory"&gt;
&lt;property name="targetConnectionFactory" ref="jmsConnectionFactory" /&gt;
&lt;/bean&gt;
&lt;/property&gt;
&lt;!-- custom MessageConverter --&gt;
&lt;property name="messageConverter" ref="defaultMessageConverter" /&gt;
&lt;/bean&gt;</pre>
<h4>&nbsp; 4. MessageConverter</h4>
<p>&nbsp;&nbsp; MessageConverter实现的是org.springframework.jms.support.converter.MessageConverter接口, 提供消息的转换功能. DefaultMessageConverter的实现见附件.</p>
<div class="dp-highlighter">
<div class="bar">
<div class="tools">Xml代码 <a title="复制代码" onclick="dp.sh.Toolbar.Command('CopyToClipboard',this);return false;" href="http://andyao.javaeye.com/blog/234101#"><img alt="复制代码" src="http://andyao.javaeye.com/images/icon_copy.gif" _counted="undefined" /></a></div>
</div>
<ol class="dp-xml">
    <li><span><span class="tag">&lt;</span><span class="tag-name">bean</span><span>&nbsp;</span><span class="attribute">id</span><span>=</span><span class="attribute-value">"defaultMessageConverter"</span><span>&nbsp;</span><span class="attribute">class</span><span>=</span><span class="attribute-value">"com.andyao.activemq.DefaultMessageConverter"</span><span>&nbsp;</span><span class="tag">/&gt;</span><span>&nbsp;&nbsp;</span></span></li>
</ol>
</div>
<pre class="xml" style="display: none" name="code">&lt;bean id="defaultMessageConverter" class="com.andyao.activemq.DefaultMessageConverter" /&gt;</pre>
<h4>&nbsp; 5. MessageProducer</h4>
<p>&nbsp;&nbsp; 实例拥有两个消息生产者, 消息生产者都是POJO, 实现见附件.</p>
<div class="dp-highlighter">
<div class="bar">
<div class="tools">Xml代码 <a title="复制代码" onclick="dp.sh.Toolbar.Command('CopyToClipboard',this);return false;" href="http://andyao.javaeye.com/blog/234101#"><img alt="复制代码" src="http://andyao.javaeye.com/images/icon_copy.gif" _counted="undefined" /></a></div>
</div>
<ol class="dp-xml">
    <li><span><span class="comments">&lt;!--&nbsp;POJO&nbsp;which&nbsp;send&nbsp;Message&nbsp;uses&nbsp;&nbsp;Spring&nbsp;JmsTemplate&nbsp;--&gt;</span><span>&nbsp;&nbsp;</span></span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="tag">&lt;</span><span class="tag-name">bean</span><span>&nbsp;</span><span class="attribute">id</span><span>=</span><span class="attribute-value">"topicMessageProducer"</span><span>&nbsp;</span><span class="attribute">class</span><span>=</span><span class="attribute-value">"com.andyao.activemq.TopicMessageProducer"</span><span class="tag">&gt;</span><span>&nbsp;&nbsp;</span></span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="tag">&lt;</span><span class="tag-name">property</span><span>&nbsp;</span><span class="attribute">name</span><span>=</span><span class="attribute-value">"template"</span><span>&nbsp;</span><span class="attribute">ref</span><span>=</span><span class="attribute-value">"jmsTemplate"</span><span>&nbsp;</span><span class="tag">/&gt;</span><span>&nbsp;&nbsp;</span></span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="tag">&lt;</span><span class="tag-name">property</span><span>&nbsp;</span><span class="attribute">name</span><span>=</span><span class="attribute-value">"destination"</span><span>&nbsp;</span><span class="attribute">ref</span><span>=</span><span class="attribute-value">"TOPIC"</span><span>&nbsp;</span><span class="tag">/&gt;</span><span>&nbsp;&nbsp;</span></span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="tag">&lt;/</span><span class="tag-name">bean</span><span class="tag">&gt;</span><span>&nbsp;&nbsp;</span></span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="tag">&lt;</span><span class="tag-name">bean</span><span>&nbsp;</span><span class="attribute">id</span><span>=</span><span class="attribute-value">"queueMessageProducer"</span><span>&nbsp;</span><span class="attribute">class</span><span>=</span><span class="attribute-value">"com.andyao.activemq.QueuMessageProducer"</span><span class="tag">&gt;</span><span>&nbsp;&nbsp;</span></span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="tag">&lt;</span><span class="tag-name">property</span><span>&nbsp;</span><span class="attribute">name</span><span>=</span><span class="attribute-value">"template"</span><span>&nbsp;</span><span class="attribute">ref</span><span>=</span><span class="attribute-value">"jmsTemplate"</span><span>&nbsp;</span><span class="tag">/&gt;</span><span>&nbsp;&nbsp;</span></span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="tag">&lt;</span><span class="tag-name">property</span><span>&nbsp;</span><span class="attribute">name</span><span>=</span><span class="attribute-value">"destination"</span><span>&nbsp;</span><span class="attribute">ref</span><span>=</span><span class="attribute-value">"QUEUE"</span><span>&nbsp;</span><span class="tag">/&gt;</span><span>&nbsp;&nbsp;</span></span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="tag">&lt;/</span><span class="tag-name">bean</span><span class="tag">&gt;</span><span>&nbsp;&nbsp;</span></span></li>
</ol>
</div>
<pre class="xml" style="display: none" name="code">&lt;!-- POJO which send Message uses  Spring JmsTemplate --&gt;
&lt;bean id="topicMessageProducer" class="com.andyao.activemq.TopicMessageProducer"&gt;
&lt;property name="template" ref="jmsTemplate" /&gt;
&lt;property name="destination" ref="TOPIC" /&gt;
&lt;/bean&gt;
&lt;bean id="queueMessageProducer" class="com.andyao.activemq.QueuMessageProducer"&gt;
&lt;property name="template" ref="jmsTemplate" /&gt;
&lt;property name="destination" ref="QUEUE" /&gt;
&lt;/bean&gt;</pre>
<h4>&nbsp;6. MessageConsumer</h4>
<p>&nbsp;TOPIC通道有两个消息消费者, QUEUE有一个消息消费者</p>
<div class="dp-highlighter">
<div class="bar">
<div class="tools">Xml代码 <a title="复制代码" onclick="dp.sh.Toolbar.Command('CopyToClipboard',this);return false;" href="http://andyao.javaeye.com/blog/234101#"><img alt="复制代码" src="http://andyao.javaeye.com/images/icon_copy.gif" _counted="undefined" /></a></div>
</div>
<ol class="dp-xml">
    <li><span><span class="comments">&lt;!--&nbsp;&nbsp;Message&nbsp;Driven&nbsp;POJO&nbsp;(MDP)&nbsp;--&gt;</span><span>&nbsp;&nbsp;</span></span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="comments">&lt;!--&nbsp;consumer1&nbsp;for&nbsp;topic&nbsp;a&nbsp;--&gt;</span><span>&nbsp;&nbsp;</span></span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="tag">&lt;</span><span class="tag-name">bean</span><span>&nbsp;</span><span class="attribute">id</span><span>=</span><span class="attribute-value">"topicConsumerA"</span><span>&nbsp;</span><span class="attribute">class</span><span>=</span><span class="attribute-value">"com.andyao.activemq.TopicConsumerA"</span><span>&nbsp;</span><span class="tag">/&gt;</span><span>&nbsp;&nbsp;</span></span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="comments">&lt;!--&nbsp;consumer2&nbsp;for&nbsp;topic&nbsp;a&nbsp;--&gt;</span><span>&nbsp;&nbsp;</span></span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="tag">&lt;</span><span class="tag-name">bean</span><span>&nbsp;</span><span class="attribute">id</span><span>=</span><span class="attribute-value">"topicConsumerB"</span><span>&nbsp;</span><span class="attribute">class</span><span>=</span><span class="attribute-value">"com.andyao.activemq.TopicConsumerB"</span><span>&nbsp;</span><span class="tag">/&gt;</span><span>&nbsp;&nbsp;</span></span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="comments">&lt;!--&nbsp;consumer&nbsp;for&nbsp;queue&nbsp;--&gt;</span><span>&nbsp;&nbsp;</span></span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="tag">&lt;</span><span class="tag-name">bean</span><span>&nbsp;</span><span class="attribute">id</span><span>=</span><span class="attribute-value">"queueConsumer"</span><span>&nbsp;</span><span class="attribute">class</span><span>=</span><span class="attribute-value">"com.andyao.activemq.QueueConsumer"</span><span>&nbsp;</span><span class="tag">/&gt;</span><span>&nbsp;&nbsp;</span></span></li>
</ol>
</div>
<pre class="xml" style="display: none" name="code">&lt;!--  Message Driven POJO (MDP) --&gt;
&lt;!-- consumer1 for topic a --&gt;
&lt;bean id="topicConsumerA" class="com.andyao.activemq.TopicConsumerA" /&gt;
&lt;!-- consumer2 for topic a --&gt;
&lt;bean id="topicConsumerB" class="com.andyao.activemq.TopicConsumerB" /&gt;
&lt;!-- consumer for queue --&gt;
&lt;bean id="queueConsumer" class="com.andyao.activemq.QueueConsumer" /&gt;</pre>
<h4>&nbsp; 7. MessageListener</h4>
<p>每一个消息消费者都对应一个MessageListener</p>
<div class="dp-highlighter">
<div class="bar">
<div class="tools">Xml代码 <a title="复制代码" onclick="dp.sh.Toolbar.Command('CopyToClipboard',this);return false;" href="http://andyao.javaeye.com/blog/234101#"><img alt="复制代码" src="http://andyao.javaeye.com/images/icon_copy.gif" _counted="undefined" /></a></div>
</div>
<ol class="dp-xml">
    <li><span><span class="tag">&lt;</span><span class="tag-name">bean</span><span>&nbsp;</span><span class="attribute">id</span><span>=</span><span class="attribute-value">"topicListenerA"</span><span>&nbsp;</span><span class="attribute">class</span><span>=</span><span class="attribute-value">"org.springframework.jms.listener.adapter.MessageListenerAdapter"</span><span class="tag">&gt;</span><span>&nbsp;&nbsp;</span></span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="tag">&lt;</span><span class="tag-name">constructor-arg</span><span>&nbsp;</span><span class="attribute">ref</span><span>=</span><span class="attribute-value">"topicConsumerA"</span><span>&nbsp;</span><span class="tag">/&gt;</span><span>&nbsp;&nbsp;</span></span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="comments">&lt;!--&nbsp;&nbsp;may&nbsp;be&nbsp;other&nbsp;method&nbsp;--&gt;</span><span>&nbsp;&nbsp;</span></span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="tag">&lt;</span><span class="tag-name">property</span><span>&nbsp;</span><span class="attribute">name</span><span>=</span><span class="attribute-value">"defaultListenerMethod"</span><span>&nbsp;</span><span class="attribute">value</span><span>=</span><span class="attribute-value">"receive"</span><span>&nbsp;</span><span class="tag">/&gt;</span><span>&nbsp;&nbsp;</span></span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="comments">&lt;!--&nbsp;custom&nbsp;MessageConverter&nbsp;define&nbsp;--&gt;</span><span>&nbsp;&nbsp;</span></span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="tag">&lt;</span><span class="tag-name">property</span><span>&nbsp;</span><span class="attribute">name</span><span>=</span><span class="attribute-value">"messageConverter"</span><span>&nbsp;</span><span class="attribute">ref</span><span>=</span><span class="attribute-value">"defaultMessageConverter"</span><span>&nbsp;</span><span class="tag">/&gt;</span><span>&nbsp;&nbsp;</span></span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="tag">&lt;/</span><span class="tag-name">bean</span><span class="tag">&gt;</span><span>&nbsp;&nbsp;</span></span></li>
    <li><span>&nbsp;&nbsp;</span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="tag">&lt;</span><span class="tag-name">bean</span><span>&nbsp;</span><span class="attribute">id</span><span>=</span><span class="attribute-value">"topicListenerB"</span><span>&nbsp;</span><span class="attribute">class</span><span>=</span><span class="attribute-value">"org.springframework.jms.listener.adapter.MessageListenerAdapter"</span><span class="tag">&gt;</span><span>&nbsp;&nbsp;</span></span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="tag">&lt;</span><span class="tag-name">constructor-arg</span><span>&nbsp;</span><span class="attribute">ref</span><span>=</span><span class="attribute-value">"topicConsumerB"</span><span>&nbsp;</span><span class="tag">/&gt;</span><span>&nbsp;&nbsp;</span></span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="comments">&lt;!--&nbsp;&nbsp;may&nbsp;be&nbsp;other&nbsp;method&nbsp;--&gt;</span><span>&nbsp;&nbsp;</span></span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="tag">&lt;</span><span class="tag-name">property</span><span>&nbsp;</span><span class="attribute">name</span><span>=</span><span class="attribute-value">"defaultListenerMethod"</span><span>&nbsp;</span><span class="attribute">value</span><span>=</span><span class="attribute-value">"receive"</span><span>&nbsp;</span><span class="tag">/&gt;</span><span>&nbsp;&nbsp;</span></span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="comments">&lt;!--&nbsp;custom&nbsp;MessageConverter&nbsp;define&nbsp;--&gt;</span><span>&nbsp;&nbsp;</span></span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="tag">&lt;</span><span class="tag-name">property</span><span>&nbsp;</span><span class="attribute">name</span><span>=</span><span class="attribute-value">"messageConverter"</span><span>&nbsp;</span><span class="attribute">ref</span><span>=</span><span class="attribute-value">"defaultMessageConverter"</span><span>&nbsp;</span><span class="tag">/&gt;</span><span>&nbsp;&nbsp;</span></span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="tag">&lt;/</span><span class="tag-name">bean</span><span class="tag">&gt;</span><span>&nbsp;&nbsp;</span></span></li>
    <li><span>&nbsp;&nbsp;</span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="tag">&lt;</span><span class="tag-name">bean</span><span>&nbsp;</span><span class="attribute">id</span><span>=</span><span class="attribute-value">"queueListener"</span><span>&nbsp;</span><span class="attribute">class</span><span>=</span><span class="attribute-value">"org.springframework.jms.listener.adapter.MessageListenerAdapter"</span><span class="tag">&gt;</span><span>&nbsp;&nbsp;</span></span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="tag">&lt;</span><span class="tag-name">constructor-arg</span><span>&nbsp;</span><span class="attribute">ref</span><span>=</span><span class="attribute-value">"queueConsumer"</span><span>&nbsp;</span><span class="tag">/&gt;</span><span>&nbsp;&nbsp;</span></span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="comments">&lt;!--&nbsp;&nbsp;may&nbsp;be&nbsp;other&nbsp;method&nbsp;--&gt;</span><span>&nbsp;&nbsp;</span></span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="tag">&lt;</span><span class="tag-name">property</span><span>&nbsp;</span><span class="attribute">name</span><span>=</span><span class="attribute-value">"defaultListenerMethod"</span><span>&nbsp;</span><span class="attribute">value</span><span>=</span><span class="attribute-value">"receive"</span><span>&nbsp;</span><span class="tag">/&gt;</span><span>&nbsp;&nbsp;</span></span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="comments">&lt;!--&nbsp;custom&nbsp;MessageConverter&nbsp;define&nbsp;--&gt;</span><span>&nbsp;&nbsp;</span></span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="tag">&lt;</span><span class="tag-name">property</span><span>&nbsp;</span><span class="attribute">name</span><span>=</span><span class="attribute-value">"messageConverter"</span><span>&nbsp;</span><span class="attribute">ref</span><span>=</span><span class="attribute-value">"defaultMessageConverter"</span><span>&nbsp;</span><span class="tag">/&gt;</span><span>&nbsp;&nbsp;</span></span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="tag">&lt;/</span><span class="tag-name">bean</span><span class="tag">&gt;</span><span>&nbsp;&nbsp;</span></span></li>
</ol>
</div>
<pre class="xml" style="display: none" name="code">&lt;bean id="topicListenerA" class="org.springframework.jms.listener.adapter.MessageListenerAdapter"&gt;
&lt;constructor-arg ref="topicConsumerA" /&gt;
&lt;!--  may be other method --&gt;
&lt;property name="defaultListenerMethod" value="receive" /&gt;
&lt;!-- custom MessageConverter define --&gt;
&lt;property name="messageConverter" ref="defaultMessageConverter" /&gt;
&lt;/bean&gt;
&lt;bean id="topicListenerB" class="org.springframework.jms.listener.adapter.MessageListenerAdapter"&gt;
&lt;constructor-arg ref="topicConsumerB" /&gt;
&lt;!--  may be other method --&gt;
&lt;property name="defaultListenerMethod" value="receive" /&gt;
&lt;!-- custom MessageConverter define --&gt;
&lt;property name="messageConverter" ref="defaultMessageConverter" /&gt;
&lt;/bean&gt;
&lt;bean id="queueListener" class="org.springframework.jms.listener.adapter.MessageListenerAdapter"&gt;
&lt;constructor-arg ref="queueConsumer" /&gt;
&lt;!--  may be other method --&gt;
&lt;property name="defaultListenerMethod" value="receive" /&gt;
&lt;!-- custom MessageConverter define --&gt;
&lt;property name="messageConverter" ref="defaultMessageConverter" /&gt;
&lt;/bean&gt;</pre>
<h4>&nbsp;8. MessageListenerContainer</h4>
<p>&nbsp;有几个MessageListener既有几个MessageListenerContainer</p>
<div class="dp-highlighter">
<div class="bar">
<div class="tools">Xml代码 <a title="复制代码" onclick="dp.sh.Toolbar.Command('CopyToClipboard',this);return false;" href="http://andyao.javaeye.com/blog/234101#"><img alt="复制代码" src="http://andyao.javaeye.com/images/icon_copy.gif" _counted="undefined" /></a></div>
</div>
<ol class="dp-xml">
    <li><span><span class="tag">&lt;</span><span class="tag-name">bean</span><span>&nbsp;</span><span class="attribute">id</span><span>=</span><span class="attribute-value">"topicListenerContainerA"</span><span>&nbsp;</span><span class="attribute">class</span><span>=</span><span class="attribute-value">"org.springframework.jms.listener.DefaultMessageListenerContainer"</span><span class="tag">&gt;</span><span>&nbsp;&nbsp;</span></span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="tag">&lt;</span><span class="tag-name">property</span><span>&nbsp;</span><span class="attribute">name</span><span>=</span><span class="attribute-value">"connectionFactory"</span><span>&nbsp;</span><span class="attribute">ref</span><span>=</span><span class="attribute-value">"jmsConnectionFactory"</span><span>&nbsp;</span><span class="tag">/&gt;</span><span>&nbsp;&nbsp;</span></span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="tag">&lt;</span><span class="tag-name">property</span><span>&nbsp;</span><span class="attribute">name</span><span>=</span><span class="attribute-value">"destination"</span><span>&nbsp;</span><span class="attribute">ref</span><span>=</span><span class="attribute-value">"TOPIC"</span><span>&nbsp;</span><span class="tag">/&gt;</span><span>&nbsp;&nbsp;</span></span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="tag">&lt;</span><span class="tag-name">property</span><span>&nbsp;</span><span class="attribute">name</span><span>=</span><span class="attribute-value">"messageListener"</span><span>&nbsp;</span><span class="attribute">ref</span><span>=</span><span class="attribute-value">"topicListenerA"</span><span>&nbsp;</span><span class="tag">/&gt;</span><span>&nbsp;&nbsp;</span></span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="tag">&lt;/</span><span class="tag-name">bean</span><span class="tag">&gt;</span><span>&nbsp;&nbsp;</span></span></li>
    <li><span>&nbsp;&nbsp;</span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="tag">&lt;</span><span class="tag-name">bean</span><span>&nbsp;</span><span class="attribute">id</span><span>=</span><span class="attribute-value">"topicListenerContainerB"</span><span>&nbsp;</span><span class="attribute">class</span><span>=</span><span class="attribute-value">"org.springframework.jms.listener.DefaultMessageListenerContainer"</span><span class="tag">&gt;</span><span>&nbsp;&nbsp;</span></span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="tag">&lt;</span><span class="tag-name">property</span><span>&nbsp;</span><span class="attribute">name</span><span>=</span><span class="attribute-value">"connectionFactory"</span><span>&nbsp;</span><span class="attribute">ref</span><span>=</span><span class="attribute-value">"jmsConnectionFactory"</span><span>&nbsp;</span><span class="tag">/&gt;</span><span>&nbsp;&nbsp;</span></span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="tag">&lt;</span><span class="tag-name">property</span><span>&nbsp;</span><span class="attribute">name</span><span>=</span><span class="attribute-value">"destination"</span><span>&nbsp;</span><span class="attribute">ref</span><span>=</span><span class="attribute-value">"TOPIC"</span><span>&nbsp;</span><span class="tag">/&gt;</span><span>&nbsp;&nbsp;</span></span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="tag">&lt;</span><span class="tag-name">property</span><span>&nbsp;</span><span class="attribute">name</span><span>=</span><span class="attribute-value">"messageListener"</span><span>&nbsp;</span><span class="attribute">ref</span><span>=</span><span class="attribute-value">"topicListenerB"</span><span>&nbsp;</span><span class="tag">/&gt;</span><span>&nbsp;&nbsp;</span></span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="tag">&lt;/</span><span class="tag-name">bean</span><span class="tag">&gt;</span><span>&nbsp;&nbsp;</span></span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;</span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="tag">&lt;</span><span class="tag-name">bean</span><span>&nbsp;</span><span class="attribute">id</span><span>=</span><span class="attribute-value">"queueListenerContainer"</span><span>&nbsp;</span><span class="attribute">class</span><span>=</span><span class="attribute-value">"org.springframework.jms.listener.DefaultMessageListenerContainer"</span><span class="tag">&gt;</span><span>&nbsp;&nbsp;</span></span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="tag">&lt;</span><span class="tag-name">property</span><span>&nbsp;</span><span class="attribute">name</span><span>=</span><span class="attribute-value">"connectionFactory"</span><span>&nbsp;</span><span class="attribute">ref</span><span>=</span><span class="attribute-value">"jmsConnectionFactory"</span><span>&nbsp;</span><span class="tag">/&gt;</span><span>&nbsp;&nbsp;</span></span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="tag">&lt;</span><span class="tag-name">property</span><span>&nbsp;</span><span class="attribute">name</span><span>=</span><span class="attribute-value">"destination"</span><span>&nbsp;</span><span class="attribute">ref</span><span>=</span><span class="attribute-value">"QUEUE"</span><span>&nbsp;</span><span class="tag">/&gt;</span><span>&nbsp;&nbsp;</span></span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="tag">&lt;</span><span class="tag-name">property</span><span>&nbsp;</span><span class="attribute">name</span><span>=</span><span class="attribute-value">"messageListener"</span><span>&nbsp;</span><span class="attribute">ref</span><span>=</span><span class="attribute-value">"queueListener"</span><span>&nbsp;</span><span class="tag">/&gt;</span><span>&nbsp;&nbsp;</span></span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="tag">&lt;/</span><span class="tag-name">bean</span><span class="tag">&gt;</span><span>&nbsp;&nbsp;</span></span></li>
</ol>
</div>
<pre class="xml" style="display: none" name="code">&lt;bean id="topicListenerContainerA" class="org.springframework.jms.listener.DefaultMessageListenerContainer"&gt;
&lt;property name="connectionFactory" ref="jmsConnectionFactory" /&gt;
&lt;property name="destination" ref="TOPIC" /&gt;
&lt;property name="messageListener" ref="topicListenerA" /&gt;
&lt;/bean&gt;
&lt;bean id="topicListenerContainerB" class="org.springframework.jms.listener.DefaultMessageListenerContainer"&gt;
&lt;property name="connectionFactory" ref="jmsConnectionFactory" /&gt;
&lt;property name="destination" ref="TOPIC" /&gt;
&lt;property name="messageListener" ref="topicListenerB" /&gt;
&lt;/bean&gt;
&lt;bean id="queueListenerContainer" class="org.springframework.jms.listener.DefaultMessageListenerContainer"&gt;
&lt;property name="connectionFactory" ref="jmsConnectionFactory" /&gt;
&lt;property name="destination" ref="QUEUE" /&gt;
&lt;property name="messageListener" ref="queueListener" /&gt;
&lt;/bean&gt;</pre>
<h3>&nbsp; Summary</h3>
<p>写spring配置文件的时候, 要把MessageProducer, MessageConsumer,MessageListener,MessageListenerContainer几个地方弄清楚:</p>
<ol>
    <li>可以有一个或者多个消息生产者向同一个destination发送消息.
    <li>queue类型的只能有一个消息消费者.
    <li>topic类型的可以有多个消息消费者.
    <li>每个消费者对应一个MessageListener和一个MessageListenerContainer. </li>
</ol>
<p>&nbsp;</p>
<img src ="http://www.blogjava.net/libin2722/aggbug/249400.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/libin2722/" target="_blank">礼物</a> 2008-12-31 22:10 <a href="http://www.blogjava.net/libin2722/articles/249400.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>ActiveMQ5.0实战二: 基本配置</title><link>http://www.blogjava.net/libin2722/articles/249399.html</link><dc:creator>礼物</dc:creator><author>礼物</author><pubDate>Wed, 31 Dec 2008 14:09:00 GMT</pubDate><guid>http://www.blogjava.net/libin2722/articles/249399.html</guid><wfw:comment>http://www.blogjava.net/libin2722/comments/249399.html</wfw:comment><comments>http://www.blogjava.net/libin2722/articles/249399.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/libin2722/comments/commentRss/249399.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/libin2722/services/trackbacks/249399.html</trackback:ping><description><![CDATA[<h3>简介</h3>
<p>上一篇http://www.javaeye.com/topic/15317介绍了ActiveMQ5.0的安装，这一篇将介绍的配置。ActiveMQ包含了很多features（详见<a href="http://activemq.apache.org/features.html" target="_blank">http://activemq.apache.org/features.html</a> ），&nbsp;&nbsp; <br />
不同的需求，不同的环境，需要不同的features，当然需要不同的配置。在这里我只写了最基本的配置，算是抛砖了，希望引出更多关于ActiveMQ的高级配置。<br />
假设已经正确安装ActiveMQ5.0，同时及其IP地址为192.168.1.148，具体使用时可以改为自己的IP。下面讲解的配置实现的features如下：</p>
<ol>
    <li>客户端可以通过tcp://192.168.1.148连接ActiveMQ。
    <li>消息持久化保存，重启服务器不会丢失消息。
    <li>可以通过http://192.168.1.148:8161/admin监控ActiveMQ服务器 </li>
</ol>
<h3>配置</h3>
<p>ActiveMQ默认使用的是XML格式配置，从4.0版本开始用MBean的方式实现XML配置，配置文件在${activemq.home}/conf目录下，文件名为activemq.xml。最新的默认配置见<br />
<a href="http://svn.apache.org/repos/asf/activemq/trunk/assembly/src/release/conf/activemq.xml" target="_blank">http://svn.apache.org/repos/asf/activemq/trunk/assembly/src/release/conf/activemq.xml</a> 。下面为本篇文章使用的配置，及重要部分的解释。</p>
<p>&nbsp;</p>
<div class="dp-highlighter">
<div class="bar">
<div class="tools">Xml代码 <a title="复制代码" onclick="dp.sh.Toolbar.Command('CopyToClipboard',this);return false;" href="http://andyao.javaeye.com/blog/154092#"><img alt="复制代码" src="http://andyao.javaeye.com/images/icon_copy.gif" _counted="undefined" /></a></div>
</div>
<ol class="dp-xml">
    <li><span><span class="tag">&lt;</span><span class="tag-name">beans</span><span>&nbsp;&nbsp;</span></span></li>
    <li><span>&nbsp;&nbsp;</span><span class="attribute">xmlns</span><span>=</span><span class="attribute-value">"http://www.springframework.org/schema/beans"</span><span>&nbsp;&nbsp;</span></span></li>
    <li><span>&nbsp;&nbsp;</span><span class="attribute">xmlns:amq</span><span>=</span><span class="attribute-value">"http://activemq.org/config/1.0"</span><span>&nbsp;&nbsp;</span></span></li>
    <li><span>&nbsp;&nbsp;</span><span class="attribute">xmlns:xsi</span><span>=</span><span class="attribute-value">"http://www.w3.org/2001/XMLSchema-instance"</span><span>&nbsp;&nbsp;</span><span class="attribute">xsi:schemaLocation</span><span>="http://www.springframework.org/schema/beans&nbsp;http://www.springframework.org/schema/beans/spring-beans-2.0.xsd &nbsp;&nbsp;</span></span></li>
    <li><span>&nbsp;&nbsp;http://activemq.org/config/1.0&nbsp;http://activemq.apache.org/schema/activemq-core.xsd &nbsp;&nbsp;</span></li>
    <li><span>&nbsp;&nbsp;http://activemq.apache.org/camel/schema/spring</span><span class="tag">&gt;</span><span>&nbsp;&nbsp;</span></span></li>
    <li><span>&nbsp; &nbsp;&nbsp;</span></li>
    <li><span>&nbsp;&nbsp;</span><span class="comments">&lt;!--&nbsp;persistent="true"表示要持久化存储消息，和子元素persistenceAdapter结合使用&nbsp;--&gt;</span><span>&nbsp;&nbsp;</span></span></li>
    <li><span>&nbsp;&nbsp;</span><span class="comments">&lt;!--&nbsp;dataDirectory默认的存储持久化数据的目录&nbsp;--&gt;</span><span>&nbsp;&nbsp;</span></span></li>
    <li><span>&nbsp;&nbsp;</span><span class="comments">&lt;!--&nbsp;brokerName&nbsp;设置broker的name，在注意在网络上必须是唯一的--&gt;</span><span>&nbsp;&nbsp;</span></span></li>
    <li><span>&nbsp;&nbsp;</span><span class="comments">&lt;!--&nbsp;更多参考http://activemq.apache.org/xbean-xml-reference-50.html#XBeanXMLReference5.0-brokerelement&nbsp;--&gt;</span><span>&nbsp;&nbsp;</span></span></li>
    <li><span>&nbsp;&nbsp;</span><span class="tag">&lt;</span><span class="tag-name">broker</span><span>&nbsp;</span><span class="attribute">xmlns</span><span>=</span><span class="attribute-value">"http://activemq.org/config/1.0"</span><span>&nbsp;</span><span class="attribute">brokerName</span><span>=</span><span class="attribute-value">"192.168.1.148"</span><span>&nbsp;</span><span class="attribute">persistent</span><span>&nbsp;=</span><span class="attribute-value">"true"</span><span>&nbsp;</span><span class="attribute">dataDirectory</span><span>=</span><span class="attribute-value">"${activemq.base}/data"</span><span>&nbsp;</span><span class="attribute">useShutdownHook</span><span>=</span><span class="attribute-value">"false"</span><span class="tag">&gt;</span><span>&nbsp;&nbsp;</span></span></li>
    <li><span>&nbsp; &nbsp;&nbsp;</span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="comments">&lt;!--&nbsp;Destination&nbsp;specific&nbsp;policies&nbsp;using&nbsp;destination&nbsp;names&nbsp;or&nbsp;wildcards&nbsp;--&gt;</span><span>&nbsp;&nbsp;</span></span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="comments">&lt;!--&nbsp;wildcards意义见http://activemq.apache.org/wildcards.html&nbsp;--&gt;</span><span>&nbsp;&nbsp;</span></span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="tag">&lt;</span><span class="tag-name">destinationPolicy</span><span class="tag">&gt;</span><span>&nbsp;&nbsp;</span></span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="tag">&lt;</span><span class="tag-name">policyMap</span><span class="tag">&gt;</span><span>&nbsp;&nbsp;</span></span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="tag">&lt;</span><span class="tag-name">policyEntries</span><span class="tag">&gt;</span><span>&nbsp;&nbsp;</span></span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="comments">&lt;!--&nbsp;这里使用了wildcards，表示所有以EUCITA开头的topic&nbsp;--&gt;</span><span>&nbsp;&nbsp;</span></span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="tag">&lt;</span><span class="tag-name">policyEntry</span><span>&nbsp;</span><span class="attribute">topic</span><span>=</span><span class="attribute-value">"EUCITA.&gt;"</span><span>&nbsp;</span><span class="attribute">producerFlowControl</span><span>=</span><span class="attribute-value">"false"</span><span>&nbsp;</span><span class="attribute">memoryLimit</span><span>=</span><span class="attribute-value">"10mb"</span><span class="tag">&gt;</span><span>&nbsp;&nbsp;</span></span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="comments">&lt;!--&nbsp;分发策略&nbsp;--&gt;</span><span>&nbsp;&nbsp;</span></span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="tag">&lt;</span><span class="tag-name">dispatchPolicy</span><span class="tag">&gt;</span><span>&nbsp;&nbsp;</span></span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="comments">&lt;!--&nbsp;按顺序分发&nbsp;--&gt;</span><span>&nbsp;&nbsp;</span></span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="tag">&lt;</span><span class="tag-name">strictOrderDispatchPolicy</span><span class="tag">/&gt;</span><span>&nbsp;&nbsp;</span></span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="tag">&lt;/</span><span class="tag-name">dispatchPolicy</span><span class="tag">&gt;</span><span>&nbsp;&nbsp;</span></span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="comments">&lt;!--&nbsp;&nbsp;恢复策略--&gt;</span><span>&nbsp;&nbsp;</span></span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="tag">&lt;</span><span class="tag-name">subscriptionRecoveryPolicy</span><span class="tag">&gt;</span><span>&nbsp;&nbsp;</span></span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="comments">&lt;!--&nbsp;只恢复最后一个message&nbsp;--&gt;</span><span>&nbsp;&nbsp;</span></span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="tag">&lt;</span><span class="tag-name">lastImageSubscriptionRecoveryPolicy</span><span class="tag">/&gt;</span><span>&nbsp;&nbsp;</span></span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="tag">&lt;/</span><span class="tag-name">subscriptionRecoveryPolicy</span><span class="tag">&gt;</span><span>&nbsp;&nbsp;</span></span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="tag">&lt;/</span><span class="tag-name">policyEntry</span><span class="tag">&gt;</span><span>&nbsp;&nbsp;</span></span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="tag">&lt;/</span><span class="tag-name">policyEntries</span><span class="tag">&gt;</span><span>&nbsp;&nbsp;</span></span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="tag">&lt;/</span><span class="tag-name">policyMap</span><span class="tag">&gt;</span><span>&nbsp;&nbsp;</span></span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="tag">&lt;/</span><span class="tag-name">destinationPolicy</span><span class="tag">&gt;</span><span>&nbsp;&nbsp;</span></span></li>
    <li><span>&nbsp;&nbsp;</span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="comments">&lt;!--&nbsp;The&nbsp;transport&nbsp;connectors&nbsp;ActiveMQ&nbsp;will&nbsp;listen&nbsp;to&nbsp;--&gt;</span><span>&nbsp;&nbsp;</span></span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="tag">&lt;</span><span class="tag-name">transportConnectors</span><span class="tag">&gt;</span><span>&nbsp;&nbsp;</span></span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="tag">&lt;</span><span class="tag-name">transportConnector</span><span>&nbsp;</span><span class="attribute">name</span><span>=</span><span class="attribute-value">"openwire"</span><span>&nbsp;</span><span class="attribute">uri</span><span>=</span><span class="attribute-value">"tcp://192.168.1.148:61616"</span><span>&nbsp;</span><span class="attribute">discoveryUri</span><span>=</span><span class="attribute-value">"multicast://default"</span><span class="tag">/&gt;</span><span>&nbsp;&nbsp;</span></span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="tag">&lt;</span><span class="tag-name">transportConnector</span><span>&nbsp;</span><span class="attribute">name</span><span>=</span><span class="attribute-value">"ssl"</span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="attribute">uri</span><span>=</span><span class="attribute-value">"ssl://192.168.1.148:61617"</span><span class="tag">/&gt;</span><span>&nbsp;&nbsp;</span></span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="tag">&lt;</span><span class="tag-name">transportConnector</span><span>&nbsp;</span><span class="attribute">name</span><span>=</span><span class="attribute-value">"stomp"</span><span>&nbsp;&nbsp;&nbsp;</span><span class="attribute">uri</span><span>=</span><span class="attribute-value">"stomp://192.168.1.148:61613"</span><span class="tag">/&gt;</span><span>&nbsp;&nbsp;</span></span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="tag">&lt;</span><span class="tag-name">transportConnector</span><span>&nbsp;</span><span class="attribute">name</span><span>=</span><span class="attribute-value">"xmpp"</span><span>&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="attribute">uri</span><span>=</span><span class="attribute-value">"xmpp://192.168.1.148:61222"</span><span class="tag">/&gt;</span><span>&nbsp;&nbsp;</span></span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="tag">&lt;/</span><span class="tag-name">transportConnectors</span><span class="tag">&gt;</span><span>&nbsp;&nbsp;</span></span></li>
    <li><span>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;</span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="comments">&lt;!--&nbsp;消息持久化方式&nbsp;--&gt;</span><span>&nbsp;&nbsp;</span></span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="tag">&lt;</span><span class="tag-name">persistenceAdapter</span><span class="tag">&gt;</span><span>&nbsp;&nbsp;</span></span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="tag">&lt;</span><span class="tag-name">amqPersistenceAdapter</span><span>&nbsp;</span><span class="attribute">directory</span><span>=</span><span class="attribute-value">"${activemq.base}/data"</span><span class="tag">/&gt;</span><span>&nbsp;&nbsp;</span></span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="tag">&lt;/</span><span class="tag-name">persistenceAdapter</span><span class="tag">&gt;</span><span>&nbsp;&nbsp;</span></span></li>
    <li><span class="tag">&lt;/</span><span class="tag-name">broker</span><span class="tag">&gt;</span><span>&nbsp;&nbsp;</span></span></li>
    <li><span>&nbsp;&nbsp;</span></li>
    <li><span>&nbsp;&nbsp;</span><span class="comments">&lt;!--&nbsp;lets&nbsp;create&nbsp;a&nbsp;command&nbsp;agent&nbsp;to&nbsp;respond&nbsp;to&nbsp;message&nbsp;based&nbsp;admin&nbsp;commands&nbsp;on&nbsp;the&nbsp;ActiveMQ.Agent&nbsp;topic&nbsp;--&gt;</span><span>&nbsp;&nbsp;</span></span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="tag">&lt;</span><span class="tag-name">commandAgent</span><span>&nbsp;</span><span class="attribute">xmlns</span><span>=</span><span class="attribute-value">"http://activemq.org/config/1.0"</span><span class="tag">/&gt;</span><span>&nbsp;&nbsp;</span></span></li>
    <li><span>&nbsp;&nbsp; &nbsp;&nbsp;</span></li>
    <li><span>&nbsp;&nbsp;</span><span class="comments">&lt;!--&nbsp;An&nbsp;embedded&nbsp;servlet&nbsp;engine&nbsp;for&nbsp;serving&nbsp;up&nbsp;the&nbsp;Admin&nbsp;console&nbsp;--&gt;</span><span>&nbsp;&nbsp;</span></span></li>
    <li><span>&nbsp;&nbsp;</span><span class="tag">&lt;</span><span class="tag-name">jetty</span><span>&nbsp;</span><span class="attribute">xmlns</span><span>=</span><span class="attribute-value">"http://mortbay.com/schemas/jetty/1.0"</span><span class="tag">&gt;</span><span>&nbsp;&nbsp;</span></span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="tag">&lt;</span><span class="tag-name">connectors</span><span class="tag">&gt;</span><span>&nbsp;&nbsp;</span></span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="tag">&lt;</span><span class="tag-name">nioConnector</span><span>&nbsp;</span><span class="attribute">port</span><span>=</span><span class="attribute-value">"8161"</span><span>&nbsp;</span><span class="tag">/&gt;</span><span>&nbsp;&nbsp;</span></span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="tag">&lt;/</span><span class="tag-name">connectors</span><span class="tag">&gt;</span><span>&nbsp;&nbsp;</span></span></li>
    <li><span>&nbsp;&nbsp;</span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="tag">&lt;</span><span class="tag-name">handlers</span><span class="tag">&gt;</span><span>&nbsp;&nbsp;</span></span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="tag">&lt;</span><span class="tag-name">webAppContext</span><span>&nbsp;</span><span class="attribute">contextPath</span><span>=</span><span class="attribute-value">"/admin"</span><span>&nbsp;</span><span class="attribute">resourceBase</span><span>=</span><span class="attribute-value">"${activemq.base}/webapps/admin"</span><span>&nbsp;</span><span class="attribute">logUrlOnStart</span><span>=</span><span class="attribute-value">"true"</span><span>&nbsp;</span><span class="tag">/&gt;</span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;</span></span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="tag">&lt;</span><span class="tag-name">webAppContext</span><span>&nbsp;</span><span class="attribute">contextPath</span><span>=</span><span class="attribute-value">"/demo"</span><span>&nbsp;</span><span class="attribute">resourceBase</span><span>=</span><span class="attribute-value">"${activemq.base}/webapps/demo"</span><span>&nbsp;</span><span class="attribute">logUrlOnStart</span><span>=</span><span class="attribute-value">"true"</span><span>&nbsp;</span><span class="tag">/&gt;</span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;</span></span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="tag">&lt;/</span><span class="tag-name">handlers</span><span class="tag">&gt;</span><span>&nbsp;&nbsp;</span></span></li>
    <li><span>&nbsp;&nbsp;</span><span class="tag">&lt;/</span><span class="tag-name">jetty</span><span class="tag">&gt;</span><span>&nbsp; &nbsp;&nbsp;</span></span></li>
    <li><span class="tag">&lt;/</span><span class="tag-name">beans</span><span class="tag">&gt;</span><span>&nbsp;&nbsp;</span></span></li>
</ol>
</div>
<pre class="xml" style="display: none" name="code">&lt;beans
xmlns="http://www.springframework.org/schema/beans"
xmlns:amq="http://activemq.org/config/1.0"
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.org/config/1.0 http://activemq.apache.org/schema/activemq-core.xsd
http://activemq.apache.org/camel/schema/spring&gt;
&lt;!-- persistent="true"表示要持久化存储消息，和子元素persistenceAdapter结合使用 --&gt;
&lt;!-- dataDirectory默认的存储持久化数据的目录 --&gt;
&lt;!-- brokerName 设置broker的name，在注意在网络上必须是唯一的--&gt;
&lt;!-- 更多参考http://activemq.apache.org/xbean-xml-reference-50.html#XBeanXMLReference5.0-brokerelement --&gt;
&lt;broker xmlns="http://activemq.org/config/1.0" brokerName="192.168.1.148" persistent ="true" dataDirectory="${activemq.base}/data" useShutdownHook="false"&gt;
&lt;!-- Destination specific policies using destination names or wildcards --&gt;
&lt;!-- wildcards意义见http://activemq.apache.org/wildcards.html --&gt;
&lt;destinationPolicy&gt;
&lt;policyMap&gt;
&lt;policyEntries&gt;
&lt;!-- 这里使用了wildcards，表示所有以EUCITA开头的topic --&gt;
&lt;policyEntry topic="EUCITA.&gt;" producerFlowControl="false" memoryLimit="10mb"&gt;
&lt;!-- 分发策略 --&gt;
&lt;dispatchPolicy&gt;
&lt;!-- 按顺序分发 --&gt;
&lt;strictOrderDispatchPolicy/&gt;
&lt;/dispatchPolicy&gt;
&lt;!--  恢复策略--&gt;
&lt;subscriptionRecoveryPolicy&gt;
&lt;!-- 只恢复最后一个message --&gt;
&lt;lastImageSubscriptionRecoveryPolicy/&gt;
&lt;/subscriptionRecoveryPolicy&gt;
&lt;/policyEntry&gt;
&lt;/policyEntries&gt;
&lt;/policyMap&gt;
&lt;/destinationPolicy&gt;
&lt;!-- The transport connectors ActiveMQ will listen to --&gt;
&lt;transportConnectors&gt;
&lt;transportConnector name="openwire" uri="tcp://192.168.1.148:61616" discoveryUri="multicast://default"/&gt;
&lt;transportConnector name="ssl"     uri="ssl://192.168.1.148:61617"/&gt;
&lt;transportConnector name="stomp"   uri="stomp://192.168.1.148:61613"/&gt;
&lt;transportConnector name="xmpp"    uri="xmpp://192.168.1.148:61222"/&gt;
&lt;/transportConnectors&gt;
&lt;!-- 消息持久化方式 --&gt;
&lt;persistenceAdapter&gt;
&lt;amqPersistenceAdapter directory="${activemq.base}/data"/&gt;
&lt;/persistenceAdapter&gt;
&lt;/broker&gt;
&lt;!-- lets create a command agent to respond to message based admin commands on the ActiveMQ.Agent topic --&gt;
&lt;commandAgent xmlns="http://activemq.org/config/1.0"/&gt;
&lt;!-- An embedded servlet engine for serving up the Admin console --&gt;
&lt;jetty xmlns="http://mortbay.com/schemas/jetty/1.0"&gt;
&lt;connectors&gt;
&lt;nioConnector port="8161" /&gt;
&lt;/connectors&gt;
&lt;handlers&gt;
&lt;webAppContext contextPath="/admin" resourceBase="${activemq.base}/webapps/admin" logUrlOnStart="true" /&gt;
&lt;webAppContext contextPath="/demo" resourceBase="${activemq.base}/webapps/demo" logUrlOnStart="true" /&gt;
&lt;/handlers&gt;
&lt;/jetty&gt;
&lt;/beans&gt;</pre>
<h3>注释</h3>
<p>关于XML配置中元素的具体信息可以参考<a href="http://activemq.apache.org/xbean-xml-reference-50.html">http://activemq.apache.org/xbean-xml-reference-50.html</a> 下面介绍本篇配置使用的一些重要元素。 </p>
<h4>DispathPolicy</h4>
<p>ActiveMQ支持3中不同的分发策略（避免翻译了以后误解，这里用原文）：</p>
<ol>
    <li>&lt;roundRobinDispatchPolicy&gt;：Simple dispatch policy that sends a message to every subscription that matches the message.
    <li>&lt;simpleDispatchPolicy&gt;：Simple dispatch policy that sends a message to every subscription that matches the message.
    <li>&lt;strictOrderDispatchPolicy&gt;：Dispatch policy that causes every subscription to see messages in the same order. </li>
</ol>
<h4>SubscriptionRecoveryPolicy</h4>
<p>ActiveMQ支持6种恢复策略，可以自行选择使用不同的策略</p>
<ol>
    <li>&lt;fixedCountSubscriptionRecoveryPolicy&gt;： keep a fixed count of last messages.
    <li>&lt;fixedSizedSubscriptionRecoveryPolicy&gt;： keep a fixed amount of memory available in RAM for message history which is evicted in time order.
    <li>&lt;lastImageSubscriptionRecoveryPolicy&gt;：only keep the last message.
    <li>&lt;noSubscriptionRecoveryPolicy&gt;：disable recovery of messages.
    <li>&lt;queryBasedSubscriptionRecoveryPolicy&gt;：perform a user specific query mechanism to load any messages they may have missed.
    <li>&lt;timedSubscriptionRecoveryPolicy&gt;：keep a timed buffer of messages around in memory and use that to recover new subscriptions. </li>
</ol>
<h4>PersistenceAdapter</h4>
<p><a href="http://activemq.apache.org/persistence.html">http://activemq.apache.org/persistence</a> 讲解了关于persistence的信息。ActiveMQ5.0使用<a href="http://activemq.apache.org/amq-message-store.html" target="_blank">AMQ Message Store</a> 持久化消息，这种方式提供了很好的性能（The AMQ Message Store is an embeddable transactional message storage solution that is extremely fast and reliable.） 默认使用该存储方式即可，如果想使用JDBC来存储，可以查找文档配置。&nbsp;</p>
<h3>Summary</h3>
<p>本篇文章只提供了基本配置信息。如果需要更多的文章，可以查看ActiveMQ的文档。</p>
<p>讲了安装和简单的配置，下一篇将介绍和Sping的整合，以及多个queue，多个topic，多个producer，多个consumer的配置，使用。</p>
<img src ="http://www.blogjava.net/libin2722/aggbug/249399.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/libin2722/" target="_blank">礼物</a> 2008-12-31 22:09 <a href="http://www.blogjava.net/libin2722/articles/249399.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>ActiveMQ5.0实战一: 安装配置ActiveMQ5.0</title><link>http://www.blogjava.net/libin2722/articles/249398.html</link><dc:creator>礼物</dc:creator><author>礼物</author><pubDate>Wed, 31 Dec 2008 14:09:00 GMT</pubDate><guid>http://www.blogjava.net/libin2722/articles/249398.html</guid><wfw:comment>http://www.blogjava.net/libin2722/comments/249398.html</wfw:comment><comments>http://www.blogjava.net/libin2722/articles/249398.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/libin2722/comments/commentRss/249398.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/libin2722/services/trackbacks/249398.html</trackback:ping><description><![CDATA[<h3>简介</h3>
<p>&nbsp; ActiveMQ 是开源的JMS实现，Geronimo应用服务器就是使用的ActiveMQ提供JMS服务。ActiveMQ5.0相比以前版本提供了一些非常有用的新功能：</p>
<ol>
    <li>AMQ Message Store (Faster Persistence!)
    <li>Cursors (To handle very large number of stored messages)
    <li>Blob Messages
    <li>Command Agent
    <li>Enterprise Integration Patterns via Camel Integration
    <li>Logging a warning if you forget to start a Connection
    <li>Message Transformation
    <li>Mirrored Queues
    <li>Flow Control&nbsp; </li>
</ol>
<p>鉴于目前关于ActiveMQ5.0的文章比较少，故准备写一系列ActiveMQ的使用方面的文章。本篇先从安装开始。&nbsp;</p>
<h3>安装</h3>
<ol>
    <li>在<a href="http://activemq.apache.org/download.html">http://activemq.apache.org/download.html</a> 下载5.0.0发行包，解压到需要安装ActiveMQ的文件夹，记为/path/to/activemq。
    <li>unix环境activemq文件夹需要执行权限，执行如下命令&nbsp; <span style="font-style: italic">chmod -R 755 /path/to/activemq&nbsp;</span> </li>
</ol>
<h3>启动</h3>
<ol>
    <li>window环境运行/path/to/activemq/bin/activemq.bat
    <li>unix环境运行/path/to/activemq/bin/activemq </li>
</ol>
<h3>测试</h3>
<p>ActiveMQ默认使用的TCP连接端口是61616, 通过查看该端口的信息可以测试ActiveMQ是否成功启动</p>
<ol>
    <li>window环境运行&nbsp; netstat -an|find "61616"
    <li>unix环境运行netstat -an|grep 61616 </li>
</ol>
<h3>监控</h3>
<p>ActiveMQ5.0版本默认启动时，启动了内置的jetty服务器，提供一个demo应用和用于监控ActiveMQ的admin应用。</p>
<p>admin：<a href="http://127.0.0.1:8161/admin/">http://127.0.0.1:8161/admin/</a> </p>
<p>demo：<a href="http://127.0.0.1:8161/demo/">http://127.0.0.1:8161/demo/</a> </p>
<p>&nbsp;</p>
<p>点击demo应用中的&#8220; <a href="http://127.0.0.1:8161/demo/portfolioPublish?count=1&amp;refresh=2&amp;stocks=IBMW&amp;stocks=BEAS&amp;stocks=MSFT&amp;stocks=SUNW">Market data publisher</a> &#8221;，就会发一些测试的消息。转到admin页面的topics menu下面（queue和topic的区别见 <a href="http://www.javaeye.com/blog/153173">http://andyao.javaeye.com/blog/153173</a> ），可以看到消息在增长。</p>
<p><img class="magplus" title="点击查看原始大小图片" height="332" alt="" src="http://www.javaeye.com/upload/picture/pic/6695/5420ab30-72c6-3b30-9492-388a5a0e5e66.gif" width="760" _counted="undefined" /> </p>
<h3>配置</h3>
<p>ActiveMQ5.0的配置文件在/path/to/activemq/conf目录下面。主要配置文件为activemq.xml，具体的配置将在后续文章中详细说明。</p>
<img src ="http://www.blogjava.net/libin2722/aggbug/249398.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/libin2722/" target="_blank">礼物</a> 2008-12-31 22:09 <a href="http://www.blogjava.net/libin2722/articles/249398.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>