JMS即Java消息服务,用于在两个应用程序之间,或分布式系统中发送消息,进行异步通信。
体系架构:JMS提供者(中间件(即JMS接口的实现)),JMS客户(生产或消费基于消息的JAVA的应用程序或对象)
JMS生产者(创建并发送消息的JMS客户)
JMS消费者(接收消息的JMS客户)
JMS消息(传递的数据对象)
JMS队列(存放消息的容器)
对象模型:
连接工厂(ConnectionFactory),有管理员创建,并绑定到JNDI树中,客户端使用JNDI查找连接工厂
JMS连接(Connection),表示JMS客户端和服务器端之间的一个活动的连接,由客户端通过调用连接工厂的方法建立的
JMS会话(Session),表示JMS客户与JMS服务器之间的会话状态,会话建立在连接上,表示客户与服务器之间的一个会话线程
JMS目的(Destination) 消息队列
生产者和消费者
JMS消息通常有两种类型:
点对点:消息分发给一个单独的使用者,点对点消息往往与队列Queue相关联,生产者知道消费者的队列,并直接将消息发送到消费者的队列,只有一个消费者获得消息
生产者不需要在接收者消费该消息期间处于运行状态,接收者也同样不需要在消息发送时处于运行状态。
发布/订阅:支持一个事件驱动模型,消息生产者和消费者都参与消息的传递,生产者发布事件,而使用者订阅感兴趣的事件,并使用事件,该消息一般与特定的
主题(Topic)关联。发布者想一个特定的消息主题发布消息,0或多个订阅者接收来自特定消息主题的消息,发布者和订阅者彼此不知道对方,好比匿名公告板。
发布者需要建立一个订阅,以便客户能够订阅,订阅者必须保持活动状态以接收消息,除非订阅者建立了持久的订阅,这种情况下,订阅者未连接时发布的消息会在订阅
者重新连接时重新发布。
ActiveMQ允许你在Spring配置文件中配置connectionFactory,在代码里直接创建JmsTemplate,也可以使用JNDI来进行配置
JmsTemplate使用时,需要确定队列,当没有明确Desination时允许定义缺省的JMS Desination来发送消息,或者通过一个字符串的名字定位Desination,在配置文件中可以
通过constructor-arg来设置队列的名字,
JmsTemplate的send()方法,他有三个重载方法,receive()也有三个重载方法,其中getReceiveTimeout方法显示的阻塞的毫秒数,默认情况下,超时被设置为-1,表示无限等待
以接受一个消息。
convertAndSend()适用于把一个Java对象转换成消息实例,并把他们直接发送出去,为了执行转换,convertAndSend()使用当前配置在JmsTemplate中的MessageConverter实例
转换的类型包括 TextMessage,MapMessage,ObjectMessage,StreamMessage,BytesMessage
receiveAndConvert()接收一个消息的时候进行转换。
JMS本地事务
想要自己管理JMS事务的话,我们使用JmsTransactionManager来代替PlatformTransactionManager,例如:以下的1没有启用事务,而2通过对1的代理,增加了事务的功能,所以
两者的最后操作结果也是不一样的。
1.
<bean id="senderTarget" class="">
<property name="jmsTemplate">
<ref bean="jmsTemplate" />
</property>
</bean>
2.
<bean id="sender" class="">
<property name="transactionManager">
<ref local=“transactionManager”/>
</property>
<property name="target">
<ref local="senderTarget"/>
</property>
<property name="transactionAttributes">
<props><prop key="send*">PROPAGATION_REQUIRED</prop></props>
</property>
</bean>
异步接收消息:接收端需要实现MessageListener接口,我们需要配置connection(JmsConnectionFactoryBean),还需要配置一个session(JmsSessionFactoryBean).
操作实例:
下载 activeMQ 5.6.0版本,解压后执行目录下activemq.bat,用来启动activeMQ
<Resource name="myJMS/ConnectionFactory"
auth="Container"
type="org.apache.activemq.ActiveMQConnectionFactory"
description="JMS Connection Factory"
factory="org.apache.activemq.jndi.JNDIReferenceFactory"
brokerURL="tcp://10.0.0.8:61616"
brokerName="MyActiveMQBroker"
useEmbeddedBroker="false"/>
<Resource name="jms/topic/MyTopic"
auth="Container"
type="org.apache.activemq.command.ActiveMQTopic"
factory="org.apache.activemq.jndi.JNDIReferenceFactory"
physicalName="MY.TEST.FOO"/>
<Resource name="jms/queue/MyQueue"
auth="Container"
type="org.apache.activemq.command.ActiveMQQueue"
factory="org.apache.activemq.jndi.JNDIReferenceFactory"
physicalName="MY.TEST.FOO.QUEUE"/>
通过JNDI配置连接工厂,点对点设置,订阅设置:
<Context docBase="D:\Maven_TEST\jt-weixin1\src\main\webapp" path="/weixin1" reloadable="false" workDir="D:\apache-tomcat-7.0.22\work\Catalina\localhost\weixi1n">
<ResourceLink global="myJMS/ConnectionFactory" name="myJMS/ConnectionFactory" />
<ResourceLink global="jms/topic/MyTopic" name="jms/topic/MyTopic" />
<ResourceLink global="jms/queue/MyQueue" name="jms/queue/MyQueue" />
</Context>
指定项目中的使用:
<resource-ref>
<description>ConnectionFactory</description>
<res-ref-name>myJMS/ConnectionFactory</res-ref-name>
<res-type>org.apache.activemq.ActiveMQConnectionFactory</res-type>
<res-auth>Container</res-auth>
</resource-ref>
<resource-ref>
<description>MyTopic</description>
<res-ref-name>jms/topic/MyTopic</res-ref-name>
<res-type>org.apache.activemq.command.ActiveMQTopic</res-type>
<res-auth>Container</res-auth>
</resource-ref>
<resource-ref>
<description>MyQueue</description>
<res-ref-name>jms/queue/MyQueue</res-ref-name>
<res-type>org.apache.activemq.command.ActiveMQQueue</res-type>
<res-auth>Container</res-auth>
</resource-ref>
Web.xml文件的配置
<bean id="connectionFactory" class="org.springframework.jndi.JndiObjectFactoryBean">
<property name="jndiName" value="java:comp/env/myJMS/ConnectionFactory"/>
</bean>
<bean id="messageQueue" class="org.springframework.jndi.JndiObjectFactoryBean">
<property name="jndiName" value="java:comp/env/jms/queue/MyQueue"></property>
</bean>
<bean id="messageTopic" class="org.springframework.jndi.JndiObjectFactoryBean">
<property name="jndiName" value="java:comp/env/jms/topic/MyTopic"></property>
</bean>
<bean id="jmsTemplate" class="org.springframework.jms.core.JmsTemplate">
<property name="connectionFactory" ref="connectionFactory"></property>
<property name="defaultDestination" ref="messageQueue"></property>
</bean>
<bean id="messageSender" class="cn.com.onezero.MessageSender">
<property name="jmsTemplate" ref="jmsTemplate"></property>
</bean>
<bean id="receiveMessageListener" class="cn.com.onezero.MessageReceiver">
</bean>
<bean id="listenerContainer"
class="org.springframework.jms.listener.DefaultMessageListenerContainer">
<property name="connectionFactory" ref="connectionFactory"></property>
<property name="destination" ref="messageQueue"></property>
<property name="messageListener" ref="receiveMessageListener"></property>
</bean>
Spring配置文件中的配置信息