activeMq整合spring

最近使用activeMQ整合spring,用侦听器容器方法写了几个异步消息机制:


一、配置文件spring-activeMq.xml:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:jms="http://www.springframework.org/schema/jms"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
                     http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/jms http://www.springframework.org/schema/jms/spring-jms.xsd">


    <!-- 1. ************************************配置JMSTemplate************************************************-->
    <!-- 真正可以产生Connection的ConnectionFactory,由对应的 JMS服务厂商提供-->
    <bean id="targetConnectionFactory" class="org.apache.activemq.ActiveMQConnectionFactory">
        <property name="brokerURL" value="tcp://localhost:61616"/>
    </bean>


    <!-- Spring用于管理真正的ConnectionFactory的ConnectionFactory -->
    <bean id="connectionFactory" class="org.springframework.jms.connection.SingleConnectionFactory">
        <!-- 目标ConnectionFactory对应真实的可以产生JMS Connection的ConnectionFactory -->
        <property name="targetConnectionFactory" ref="targetConnectionFactory"/>
    </bean>


    <!-- Spring提供的JMS工具类,它可以进行消息发送、接收等 -->
    <bean id="jmsTemplate" class="org.springframework.jms.core.JmsTemplate">
        <!-- 这个connectionFactory对应的是我们定义的Spring提供的那个ConnectionFactory对象 -->
        <property name="connectionFactory" ref="connectionFactory"/>
        <!--设置等待延时时间-->
        <property name="receiveTimeout" value="100000"/>
        <!-- 消息转换器,发送消息时默认会调用,但要使用convertAndSend()方法 -->
        <!--<property name="messageConverter" ref="emailMessageConverter"/>-->
    </bean>


    <!--事物管理-->
   <bean id="transactionManager" class="org.springframework.jms.connection.JmsTransactionManager">
        <property name="connectionFactory" ref="connectionFactory"/>
    </bean>


    <!--启动外部事物,即全局事务-->
<!--
    <bean id="jtaTransactionManager" class="org.springframework.transaction.jta.JtaTransactionManager"></bean>
-->
    <!--消息转换器-->
    <bean id="emailMessageConverter" class="spring_activeMQ.messageConveter.EmailMessageConverter"/>


    <!-- 2. **************************************定义消息队列***********************************************-->
    <!--这个是队列目的地,包含一个队列名称或主题名称的构造参数-->
    <bean id="queueDestination" class="org.apache.activemq.command.ActiveMQQueue">
        <constructor-arg>
            <value>queue</value>
        </constructor-arg>
    </bean>


    <!--这个是队列目的地,包含一个队列名称或主题名称的构造参数-->
    <bean id="queueTransDestination" class="org.apache.activemq.command.ActiveMQQueue">
        <constructor-arg>
            <value>queueTrans</value>
        </constructor-arg>
    </bean>


    <!--这个是队列目的地,包含一个队列名称或主题名称的构造参数-->
    <bean id="sessionQueueDestination" class="org.apache.activemq.command.ActiveMQQueue">
        <constructor-arg>
            <value>sessionQueue</value>
        </constructor-arg>
    </bean>


    <!--这个是队列目的地,包含一个队列名称或主题名称的构造参数-->
    <bean id="adapterDestination" class="org.apache.activemq.command.ActiveMQQueue">
        <constructor-arg>
            <value>adapterQueue</value>
        </constructor-arg>
    </bean>


    <!-- 3. ****************************************定义生产者跟消费者********************************************-->
    <!--注入消息发送者-->
    <bean id="producerService" class="spring_activeMQ.producers.ProducerImpl">
        <property name="jmsTemplate" ref="jmsTemplate"></property>
    </bean>


    <!--注入消息发送者-->
    <bean id="producerObj" class="spring_activeMQ.producers.ProducerForObject">
        <property name="jmsTemplate" ref="jmsTemplate"></property>
    </bean>


    <!--消费者1: 普通消息侦听器,注入消息侦听器,即接收者-->
    <bean id="consumerMessageListener" class="spring_activeMQ.consumers.ConsumerMessageListener">
        <!--消息转换器-->
        <property name="messageConverter" ref="emailMessageConverter"></property>
    </bean>


    <!--消费者2: 普通消息侦听器,与上面无异,但能管理事物-->
    <bean id="consumerTrascationMessageListener"  class="spring_activeMQ.consumers.ComsumerTrascationListener"></bean>


    <!--消费者3: SessionAwareMessageListener消息侦听器 -->
    <bean id="consumerSessionAwareMessageListener" class="spring_activeMQ.consumers.ConsumerSessionAwareMessageListener">
        <!--消息确认目的地属性-->
        <property name="destination" ref="queueDestination"></property>


    </bean>


    <!--消费者4: messageListenerAdapter消息侦听器 -->
    <bean id="messageListenerAdapter" class="org.springframework.jms.listener.adapter.MessageListenerAdapter">
         <!--指定处理消息的类,是普通类-->
        <property name="delegate">
            <bean class="spring_activeMQ.consumers.ConsumerAdapterListener"/>
        </property>
        <!--指定处理消息的方法,若没有指定,便调用默认处理方法:handleMessage-->
        <property name="defaultListenerMethod" value="receiveMessage"/>
        <!--指定默认的回复地址,若消息也设置了JMSReplyTo消息头属性,则使用消息头中的地址-->
        <property name="defaultResponseDestination" ref="queueDestination"/>
        <!--消息转换器,接收消息是默认调用,可以不指定-->
        <property name="messageConverter" ref="emailMessageConverter"/>
    </bean>


    <!-- 4. *************************************以下是利用jms命名空间来定义侦听器容器及侦听器***********************************-->
    <jms:listener-container connection-factory="connectionFactory" concurrency="10" transaction-manager="transactionManager">
        <!--destination:制定的队列名称; ref:指定的侦听器-->
        <jms:listener destination="queue" ref="consumerMessageListener"/>
        <jms:listener destination="sessionQueue" ref="consumerSessionAwareMessageListener"/>
        <jms:listener destination="adapterQueue" ref="messageListenerAdapter"/>
    </jms:listener-container>


    <!--*********************此方法也是定义侦听器容器及侦听器,与上面效果一样,但不推荐使用,太过累赘,每一个侦听器都配一个侦听器容器,烦的一塌糊涂************************************-->


    <!-- 消息监听容器,容器上绑定了连接工厂、消息目的地、消息侦听器的bean,这里验证事物管理 -->
    <bean id="jmsContainer" class="org.springframework.jms.listener.DefaultMessageListenerContainer">
        <!--连接工厂-->
        <property name="connectionFactory" ref="connectionFactory" />
        <!--消息目的地-->
        <property name="destination" ref="queueTransDestination" />
        <!--消息侦听器1-->
        <property name="messageListener" ref="consumerTrascationMessageListener" />
        <!--并发侦听器线程数-->
        <property name="concurrentConsumers" value="10"/>
         <!--启动事物-->
        <property name="sessionTransacted" value="true"/>
    </bean>


    <!-- SessionAwareMessageListener的消息监听容器,容器上绑定了连接工厂、消息目的地、消息侦听器的bean -->
    <!--<bean id="jmsSessionContainer" class="org.springframework.jms.listener.DefaultMessageListenerContainer">
        <!–连接工厂–>
        <property name="connectionFactory" ref="connectionFactory" />
        <!–消息目的地–>
        <property name="destination" ref="sessionQueueDestination" />
        <!–消息侦听器2–>
        <property name="messageListener" ref="consumerSessionAwareMessageListener" />
        <!–并发侦听器线程数–>
        <property name="concurrentConsumers" value="10"/>
    </bean>-->


    <!-- SessionAwareMessageListener的消息监听容器,容器上绑定了连接工厂、消息目的地、消息侦听器的bean -->
    <!-- <bean id="messageListenerAdapterContainer" class="org.springframework.jms.listener.DefaultMessageListenerContainer">
         <!–连接工厂–>
         <property name="connectionFactory" ref="connectionFactory" />
         <!–消息目的地–>
         <property name="destination" ref="adapterDestination" />
         <!–消息侦听器2–>
         <property name="messageListener" ref="messageListenerAdapter" />
         <!–并发侦听器线程数–>
         <property name="concurrentConsumers" value="10"/>
     </bean>-->


</beans>



二、配置文件spring-applications.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:util="http://www.springframework.org/schema/util"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
                     http://www.springframework.org/schema/beans/spring-beans.xsd
                     http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util.xsd">


<import resource="classpath*:beans-test.xml" />
    <import resource="classpath*:spring-activeMq.xml" />


</beans>




三、消息侦听器1


/**
 * 消息侦听器:能够进行事务管理的侦听器
 * Created with IntelliJ IDEA.
 * User: wxshi
 * Date: 15-3-17
 * Time: 下午1:50
 * To change this template use File | Settings | File Templates.
 */
public class ComsumerTrascationListener implements MessageListener {


    public void onMessage(Message message) {
        //这里我们知道生产者发送的就是一个纯文本消息,所以这里可以直接进行强制转换
        if(message instanceof TextMessage) {
            TextMessage textMsg = (TextMessage)message;
            System.out.println("接收到一个纯文本消息。");
            try {


                if (1 != 1) {      //这里抛出异常用于检测事物,此条消息会回滚,并在再次启动时再次发送
                    throw new RuntimeException("Error");
                }else{
                    System.out.println("消息内容是:" + textMsg.getText());
                    System.out.println("---------------------------------");
                }
            } catch (JMSException e) {
                e.printStackTrace();
            }
        }
    }


}



四、消息侦听器2:

/**
 * 消息侦听器:此类本来是普通类,但一旦被MessageListenerAdapter管理,便成为消息侦听器了
 * Created with IntelliJ IDEA.
 * User: wxshi
 * Date: 15-3-16
 * Time: 下午3:50
 * To change this template use File | Settings | File Templates.
 */
public class ConsumerAdapterListener {


    public void handleMessage(String message) {
        System.out.println("ConsumerListener通过handleMessage接收到一个纯文本消息,消息内容是:" + message);
    }


    //指定的处理消息方法体,若返回为空,则不回复确认信息,否则回复确认信息(自动回复)
    public String receiveMessage(String message) {
        System.out.println("ConsumerListener通过receiveMessage接收到一个纯文本消息,消息内容是:" + message);
        String replyContent = "ConsumerAdapterListener已收到消息并处理";   //回复内容
        return replyContent;   //返回时会自动回复
    }




    public void receiveMessage(Email email) {
        System.out.println("接收到一个包含Email的ObjectMessage。");
        System.out.println(email);
    }


}


五、消息侦听器3:

package spring_activeMQ.consumers;


import org.springframework.jms.support.converter.MessageConverter;
import spring_activeMQ.pojo.Email;


import javax.jms.*;


/**
 * 实现MessageListener接口的侦听器,此侦听器单纯接收消息
 * 消息侦听器,用于异步接收处理消息
 * 实现MessageListener接口
 * Created with IntelliJ IDEA.
 * User: wxshi
 * Date: 15-3-16
 * Time: 上午10:06
 * To change this template use File | Settings | File Templates.
 */
public class ConsumerMessageListener implements MessageListener {


    private MessageConverter messageConverter;


    public MessageConverter getMessageConverter() {
        return messageConverter;
    }


    public void setMessageConverter(MessageConverter messageConverter) {
        this.messageConverter = messageConverter;
    }


    public void onMessage(Message message) {
        //这里我们知道生产者发送的就是一个纯文本消息,所以这里可以直接进行强制转换
        if(message instanceof TextMessage) {
            TextMessage textMsg = (TextMessage)message;
            System.out.println("接收到一个纯文本消息。");
            try {
                System.out.println("消息内容是:" + textMsg.getText());
                System.out.println("---------------------------------");
            } catch (JMSException e) {
                e.printStackTrace();
            }
        }else if (message instanceof ObjectMessage) {
            ObjectMessage objMessage = (ObjectMessage) message;
            try {
//                Object obj = objMessage.getObject();
//                Email email = (Email) obj; //强制转换,其实也可以使用
                Email email = (Email)messageConverter.fromMessage(message);
                System.out.println("接收到一个ObjectMessage,包含Email对象。");
                System.out.println(email);
            } catch (JMSException e) {
                e.printStackTrace();
            }
        }


    }


}


六、消息侦听器4

package spring_activeMQ.consumers;


import org.springframework.jms.listener.SessionAwareMessageListener;


import javax.jms.*;


/**
 * 实现SessionAwareMessageListener接口的消息侦听器,此侦听器可以获取session用以回复确认
 * Created with IntelliJ IDEA.
 * User: wxshi
 * Date: 15-3-16
 * Time: 下午1:40
 * To change this template use File | Settings | File Templates.
 */
public class ConsumerSessionAwareMessageListener implements SessionAwareMessageListener<TextMessage> {
     //监听队列
    private Destination destination;


    public Destination getDestination() {
        return destination;
    }


    public void setDestination(Destination destination) {
        this.destination = destination;
    }
    public void onMessage(TextMessage message, Session session) throws JMSException {
        System.out.println("收到一条消息");
        System.out.println("消息内容是:" + message.getText());
        MessageProducer producer = session.createProducer(destination);
        Message textMessage = session.createTextMessage("ConsumerSessionAwareMessageListener确认回复");
        System.out.println("---------------------------------");
        producer.send(textMessage);
    }
}



七、消息生产者1

package spring_activeMQ.producers;


import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jms.core.JmsTemplate;


import javax.jms.Destination;
import java.io.Serializable;


/**
 * 词生产者会使用到消息转换器:MessageConverter
 * MessageConverter会在配置文件里进行配置
 * Created with IntelliJ IDEA.
 * User: wxshi
 * Date: 15-3-17
 * Time: 上午9:21
 * To change this template use File | Settings | File Templates.
 */
public class ProducerForObject {
    @Autowired
    private JmsTemplate jmsTemplate;


    public JmsTemplate getJmsTemplate() {
        return jmsTemplate;
    }


    public void setJmsTemplate(JmsTemplate jmsTemplate) {
        this.jmsTemplate = jmsTemplate;
    }


    public void sendMessage(Destination destination, final Serializable obj) {
        //未使用MessageConverter的情况
        /*jmsTemplate.send(destination, new MessageCreator() {
            public Message createMessage(Session session) throws JMSException {
                ObjectMessage objMessage = session.createObjectMessage(obj);
                return objMessage;
            }
        });*/
        //使用MessageConverter的情况
        jmsTemplate.convertAndSend(destination, obj);
    }
}


八、消息生产者2

package spring_activeMQ.producers;


import org.springframework.jms.core.JmsTemplate;
import org.springframework.jms.core.MessageCreator;


import javax.jms.*;


/**
 * 定义生产者,调用jmsTemplate发送消息
 * Created with IntelliJ IDEA.
 * User: wxshi
 * Date: 15-3-16
 * Time: 上午10:05
 * To change this template use File | Settings | File Templates.
 */
public class ProducerImpl{


    //jms模板
    private JmsTemplate jmsTemplate;


    public void sendMessage(Destination destination, final String message, final Destination responseDestination) {
        System.out.println("---------------生产者发了一个消息:" + message);
        jmsTemplate.send(destination, new MessageCreator() {
            public Message createMessage(Session session) throws JMSException {
                TextMessage textMessage = session.createTextMessage(message);
                if(responseDestination == null){
                    return textMessage;
                }
                textMessage.setJMSReplyTo(responseDestination);
                return textMessage;
            }
        });
    }


    public JmsTemplate getJmsTemplate() {
        return jmsTemplate;
    }


    public void setJmsTemplate(JmsTemplate jmsTemplate) {
        this.jmsTemplate = jmsTemplate;
    }
}

//测试
<pre name="code" class="java">package spring_activeMQ.test;


import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import spring_activeMQ.pojo.Email;
import spring_activeMQ.producers.ProducerForObject;
import spring_activeMQ.producers.ProducerImpl;


import javax.jms.Destination;


/**
 * Created with IntelliJ IDEA.
 * User: wxshi
 * Date: 15-3-16
 * Time: 上午10:13
 * To change this template use File | Settings | File Templates.
 */
  @RunWith(SpringJUnit4ClassRunner.class)
  @ContextConfiguration("/spring-activeMq.xml")
  public class ProducerConsumerTest {


    @Autowired
    private ProducerImpl producerImpl;


    @Autowired
    private ProducerForObject producerObj;


    @Qualifier("queueDestination")
    @Autowired
    private Destination queueDestination;


    @Qualifier("queueTransDestination")
    @Autowired
    private Destination queueTransDestination;


    @Qualifier("sessionQueueDestination")
    @Autowired
    private Destination sessionDestination;


    @Qualifier("adapterDestination")
    @Autowired
    private Destination adapterDestination;


    @Test
    public void testSend() {
        producerImpl.sendMessage(queueTransDestination, "你好,生产者!这是消息",null);
    }


    @Test    //使用到消息转换器
    public void testObjectMessage() {
        Email email = new Email("zhangsan@xxx.com", "主题", "内容");
        producerObj.sendMessage(queueDestination, email);
    }
}



 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值