ActiveMQ与Spring整合:(1)基本使用

来源:互联网 发布:安卓手机优化软件 编辑:程序博客网 时间:2024/05/18 12:02

        最近在学习Java消息服务(JMS),Java消息服务主要是用在应用间解耦。比如,我们经常用到的短信服务,一笔交易完成之后,我们可能需要发送短信,为了加快系统响应速度,我们可能需要把短信设计成异步的,我们只需要把短信发送给短信平台,最终短信是否成功交由短信平台来处理。另外一种使用场景就是支付交易,一笔支付交易完成之后,支付平台需要后台异步通知商户,支付已经成功。这个通知通常也会做成异步的。像以上两种使用场景,我们就可以使用Java消息服务来实现。

Java消息服务(JMS),只是一组规范,即API。它的具体实现由厂商自己去实现,就像JDBC一样。目前使用较多的实现有ActiveMQ,RabbitMQ,kafuka。接下来主要介绍ActiveMQ的一些基本概念以及与Spring的整合。

        JMS分为两种消息传送模式,点到点模式(P2P),发布订阅模式(Pub/Sub)模式。点到点模式组成包括:消息发送者,接受者,JMS提供者(broken服务器);P2P消息目的地称为队列Queue,且消息只能被一个接受者接受。发布订阅模式组成包括:发布者,订阅者,JMS提供者(broken服务器),发布订阅的目的地称为主题Topic,且消息能够被多个订阅者接受。

        接下来主要是介绍Spring与ActiveMQ的结合使用,主要介绍P2P消息队列。把消息发送者,消息接收者放在两个应用,使用外部ActiveMQ。

1、新建JMS消息发送者应用,ActiveMQ_Producer。applicationContext.xml如下:

<?xml version="1.0" encoding="UTF-8"?><beans xmlns="http://www.springframework.org/schema/beans"    xmlns:context="http://www.springframework.org/schema/context"    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-3.2.xsd    http://www.springframework.org/schema/context    http://www.springframework.org/schema/context/spring-context-3.2.xsd">    <!-- 连接池  -->    <bean id="pooledConnectionFactory" class="org.apache.activemq.pool.PooledConnectionFactory" destroy-method="stop">          <property name="connectionFactory">              <!-- 连接工厂 -->            <bean class="org.apache.activemq.ActiveMQConnectionFactory">                  <property name="brokerURL" value="tcp://localhost:61616" />              </bean>          </property>         <property name="maxConnections" value="10"/>       </bean>         <!-- 消息模板 -->    <bean id="jmsTemplate" class="org.springframework.jms.core.JmsTemplate">          <property name="connectionFactory" ref="pooledConnectionFactory" />          <property name="defaultDestination" ref="queueDestination" />          <property name="messageConverter">              <bean class="org.springframework.jms.support.converter.SimpleMessageConverter" />       </property>         <!-- 消息转换器 -->  <!--     <property name="messageConverter" ref="emailMessageConverter"/> -->    </bean>          <!-- 配置消息目标 -->    <bean id="queueDestination" class="org.apache.activemq.command.ActiveMQQueue">          <!-- 目标,在ActiveMQ管理员控制台创建 http://localhost:8161/admin/queues.jsp -->        <constructor-arg index="0" value="helloQueue" />      </bean>     <!-- 用于测试消息回复的 -->  <bean id="responseQueue" class="org.apache.activemq.command.ActiveMQQueue">      <constructor-arg>          <value>responseQueue</value>      </constructor-arg>  </bean>          <!-- 消息监听器 -->      <bean id="responseMessageListener" class="com.hua.spring.jms.listener.ResponseQueueMessageListener"/>           <!-- 消息监听容器 -->       <bean id="responseQueueListenerAdapter" class=" org.springframework.jms.listener.DefaultMessageListenerContainer">            <property name="connectionFactory" ref="pooledConnectionFactory" />          <property name="destination" ref="responseQueue" />          <property name="messageListener" ref="responseMessageListener" />          <property name="sessionTransacted" value="false"/>     </bean>           </beans>
主要有两个队列,一个是发送队列queueDestination,一个是用来接收响应的队列responseQueue。采用异步接受消息,所以接收响应的队列responseQueue需要配置监听器,并把监听器放入监听容器。监听器需要实现MessageListener接口,或者SessionAwareMessageListener接口。

2、新建监听器类:ResponseQueueMessageListener.java

package com.hua.spring.jms.listener;import javax.jms.JMSException;import javax.jms.Message;import javax.jms.MessageListener;import javax.jms.TextMessage;import org.slf4j.Logger;import org.slf4j.LoggerFactory;/** * @description * @date:(2016-8-25 下午10:01:07) * @author Administrator * @version v1.0 * @since v1.0 * * Modified history * *    Modified date:   *    Modifier user:      *    description:  * * */public class ResponseQueueMessageListener implements MessageListener{private Logger logger=LoggerFactory.getLogger(ResponseQueueMessageListener.class);@Overridepublic void onMessage(Message message) {if(message instanceof TextMessage){try {String text=((TextMessage) message).getText();logger.info("消息生产者接收到响应:"+text);} catch (JMSException e) {logger.error("消息生产者接收消息时发生异常:",e);}}}}
监听器类实现了MessageListener接口,这个接口只有一个方法public void onMessage(Message message)。

3、新建消息提供者启动类Main.java

package com.jms.producer.client;import javax.jms.JMSException;import javax.jms.Message;import javax.jms.Session;import javax.jms.TextMessage;import org.slf4j.Logger;import org.slf4j.LoggerFactory;import org.springframework.context.ApplicationContext;import org.springframework.context.support.ClassPathXmlApplicationContext;import org.springframework.jms.core.JmsTemplate;import org.springframework.jms.core.MessageCreator;/** * @description * @date:(2016-8-28 上午9:43:03) * @author Administrator * @version v1.0 * @since v1.0 * * Modified history * *    Modified date:   *    Modifier user:      *    description:  * * */public class Main {private static Logger logger=LoggerFactory.getLogger(Main.class);public static void main(String[] args) {ApplicationContext context=new ClassPathXmlApplicationContext("/config/applicationContext.xml");JmsTemplate jmsTemplate=(JmsTemplate)context.getBean("jmsTemplate");jmsTemplate.send("helloQueue", new MessageCreator() {@Overridepublic Message createMessage(Session session) throws JMSException {String msg="发送者:我是消息生产者";TextMessage textMessage=session.createTextMessage(msg);logger.info(msg);return textMessage;}});}}
4、另外日志输出配置文件logback.xml如下:

<configuration>        <appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender">       <!-- encoder 默认配置为PatternLayoutEncoder -->       <encoder>         <pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern>       </encoder>     </appender>        <root level="info">                 <appender-ref ref="CONSOLE" />     </root>           </configuration> 
项目目录结构如下:



5、新建消息接受者应用ActiveMQ_Consumer,applicationContext.xml如下:

<pre name="code" class="html"><?xml version="1.0" encoding="UTF-8"?><beans xmlns="http://www.springframework.org/schema/beans"    xmlns:context="http://www.springframework.org/schema/context"    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-3.2.xsd    http://www.springframework.org/schema/context    http://www.springframework.org/schema/context/spring-context-3.2.xsd">    <!-- 连接池  -->    <bean id="pooledConnectionFactory" class="org.apache.activemq.pool.PooledConnectionFactory" destroy-method="stop">          <property name="connectionFactory">              <!-- 连接工厂 -->            <bean class="org.apache.activemq.ActiveMQConnectionFactory">                  <property name="brokerURL" value="tcp://localhost:61616" />              </bean>          </property>         <property name="maxConnections" value="10"/>       </bean>         <!-- 消息模板 -->    <bean id="jmsTemplate" class="org.springframework.jms.core.JmsTemplate">          <property name="connectionFactory" ref="pooledConnectionFactory" />          <property name="defaultDestination" ref="queueDestination" />          <property name="messageConverter">              <bean class="org.springframework.jms.support.converter.SimpleMessageConverter" />       </property>         <!-- 消息转换器 -->  <!--     <property name="messageConverter" ref="emailMessageConverter"/> -->    </bean>          <!-- 配置消息目标 -->    <bean id="queueDestination" class="org.apache.activemq.command.ActiveMQQueue">          <!-- 目标,在ActiveMQ管理员控制台创建 http://localhost:8161/admin/queues.jsp -->        <constructor-arg index="0" value="helloQueue" />      </bean>     <!-- 用于测试消息回复的 -->  <bean id="responseQueue" class="org.apache.activemq.command.ActiveMQQueue">      <constructor-arg>          <value>responseQueue</value>      </constructor-arg>  </bean>    <!-- 可以获取session的MessageListener -->      <bean id="queueDestinationMessageListener" class="com.hua.spring.jms.listener.QueueDestinationMessageListener">          <property name="destination" ref="responseQueue"/>    </bean>          <!-- 消息监听容器 -->       <bean id="responseQueueListenerAdapter" class=" org.springframework.jms.listener.DefaultMessageListenerContainer">            <property name="connectionFactory" ref="pooledConnectionFactory" />          <property name="destination" ref="queueDestination" />          <property name="messageListener" ref="queueDestinationMessageListener" />          <property name="sessionTransacted" value="false"/>     </bean></beans>


消息接受者配置也是两个队列,其中要对消息发送者队列queueDestination进行监听,配置监听器并把监听器注册到监听容器。

6、新建监听器类QueueDestinationMessageListener.java。实现SessionAwareMessageListener接口,这样就可以对消息进行相应响应,不需要进行响应时可实现MessageListener接口。则不能进行

package com.hua.spring.jms.listener;import javax.jms.Destination;import javax.jms.JMSException;import javax.jms.Message;import javax.jms.MessageListener;import javax.jms.MessageProducer;import javax.jms.Session;import javax.jms.TextMessage;import org.slf4j.Logger;import org.slf4j.LoggerFactory;import org.springframework.jms.listener.SessionAwareMessageListener;/** * @description * @date:(2016-8-28 上午9:49:32) * @author Administrator * @version v1.0 * @since v1.0 * * Modified history * *    Modified date:   *    Modifier user:      *    description:  * * */public class QueueDestinationMessageListener implements SessionAwareMessageListener<Message>{private Logger logger=LoggerFactory.getLogger(QueueDestinationMessageListener.class);private Destination destination;@Overridepublic void onMessage(Message message, Session session) throws JMSException {if(message instanceof TextMessage){try {String text=((TextMessage)message).getText();logger.info("接受者:我收到消息-->"+text);MessageProducer producer = session.createProducer(destination);          Message textMessage = session.createTextMessage("我是消息接收者,我已接收到消息");          producer.send(textMessage);} catch (JMSException e) {logger.error("监听消息发生异常",e);}}}public Destination getDestination() {return destination;}public void setDestination(Destination destination) {this.destination = destination;}}
7、新建消息接受者应用的启动类:

package com.jms.client;import org.springframework.context.ApplicationContext;import org.springframework.context.support.ClassPathXmlApplicationContext;/** * @description * @date:(2016-8-28 上午10:27:43) * @author Administrator * @version v1.0 * @since v1.0 * * Modified history * *    Modified date:   *    Modifier user:      *    description:  * * */public class Consumer {public static void main(String[] args) {ApplicationContext applicationContext=new ClassPathXmlApplicationContext("/config/applicationContext.xml");}}
整体项目结构如下:



下载ActiveMQ,我用到的是apache-activemq-5.8.0,解压后如下。


进入到lib目录,如果是window环境,就点击activemq.bat;Linux环境就执行activemq这样就可以启动broken服务器了。

执行Main.java和Consumer.java可以看到如下日志:

ActiveMQ_Producer的日志:


ActiveMQ_Consumer的日志:



0 0
原创粉丝点击