Spring整合ActiveMQ(topic 详细配置步骤)

首先和大家一起回顾一下JMS服务:

  1. 消息服务:一个中间件,用于解决两个活多个程序之间的耦合,底层由Java 实现。
  2. 优势:异步、可靠
  3. 消息模型:点对点,发布/订阅
  4. JMS中的对象

事前说明:

   这里和大家讲解一下这个配置文件,如果大家能够从上述配置文件中看懂,可以跳过。同学们也可以在ActiveMQ官网中的查看。

    ActiveMq 中的DTD,我们在声明相关配置之前,我们需要先导入ActiveMq 中的DTD,不然Spring 并不理解我们的标签是什么意思。

         http://activemq.apache.org/schema/core/activemq-core-5.12.1.xsd

       1 我们在pom.xml 文件中有配置了activemq 的版本依赖我们这里的版本,需要和依赖的版本一样,不然是找不到相关的dtd

       2、amq:connectionFactory:很直白的一个配置项,用于配置我们链接工厂的地址和用户名密码,这里需要注意的是选择tcp连接而不是http连接

       3、jmsTemplate:比较重要的一个配置,这里指定了连接工厂,默认消息发送目的地,还有连接时长,发布消息的方式

maven工程添加依赖

<dependencies>
   <!-- Spring -->
   <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-web</artifactId>
   </dependency>
   <!-- ActiveMQ依赖 -->
   <dependency>
      <groupId>org.apache.activemq</groupId>
      <artifactId>activemq-client</artifactId>

   </dependency>
   <!-- 加入spring-jms依赖 -->
   <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-jms</artifactId>
   </dependency>
</dependencies>

一、创建生产者: applicationContext-activemq-topic-producer.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"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
       http://www.springframework.org/schema/beans/spring-beans.xsd">
    <!-- 真正可以产生Connection的ConnectionFactory,由对应的 JMS服务厂商提供 -->
    <bean id="targetConnectionFactory" class="org.apache.activemq.ActiveMQConnectionFactory">
        <property name="brokerURL" value="tcp://xxx.xxx.xxx.xxx: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="pubSubDomain" value="true"/>
    </bean>
    <!--订阅模式,一对多 -->
    <bean id="topicDestination" class="org.apache.activemq.command.ActiveMQTopic">
        <constructor-arg value="topic.item"/>
    </bean>
</beans>

二、创建消费者1    applicationContext-activemq-topic-consumer1.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"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
       http://www.springframework.org/schema/beans/spring-beans.xsd">
    <!-- 真正可以产生Connection的ConnectionFactory,由对应的 JMS服务厂商提供 -->
    <bean id="targetConnectionFactory" class="org.apache.activemq.ActiveMQConnectionFactory">
        <property name="brokerURL" value="tcp://xxx.xxx.xxx.xxx:61616"/>
    </bean>

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

    <!--订阅模式,一对多的 -->
    <bean id="topicDestination" class="org.apache.activemq.command.ActiveMQTopic">
        <constructor-arg value="topic.item"/>
    </bean>
    <!-- messageListener实现类 -->
    <bean id="topicMessageListener1" class="it.hehe.spring.topic.TopicMessageListener1"/>

    <!-- 配置一个jms监听容器 -->
    <bean id="jmsContainer" class="org.springframework.jms.listener.DefaultMessageListenerContainer">
        <property name="connectionFactory" ref="connectionFactory"/>
        <property name="destination" ref="topicDestination"/>
        <property name="messageListener" ref="topicMessageListener1"/>
        <!-- 消息持久化 -->
        <property name="subscriptionDurable" value="true"/>
        <!-- 消费者标识 -->
        <property name="clientId" value="topic-consumer-a"/>
        <!-- 订阅者标识(与消费者标识符可以不一样;默认为监听器全限定名) -->
        <property name="durableSubscriptionName" value="topic-consumer-a"/>
        <!-- 设置为发布/订阅模式 -->
        <property name="pubSubDomain" value="true"/>
        <!-- 是否开启事务 -->
        <property name="sessionTransacted" value="false"/>
        <!-- 客户端消息确认模式名称 -->
        <property name="sessionAcknowledgeModeName" value="CLIENT_ACKNOWLEDGE"/>
    </bean>

</beans>

二、创建消费者2    applicationContext-activemq-topic-consumer2.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"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
       http://www.springframework.org/schema/beans/spring-beans.xsd">

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

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

    <!--订阅模式,一对多的 -->
    <bean id="topicDestination" class="org.apache.activemq.command.ActiveMQTopic">
        <constructor-arg value="topic.item"/>
    </bean>

    <!-- messageListener实现类 -->
  <bean id="topicMessageListener2" class="it
.hehe.spring.topic.TopicMessageListener2"/>
<!-- 配置一个jms监听容器 -->
<bean id="jmsContainer" class="org.springframework.jms.listener.DefaultMessageListenerContainer">
    <property name="connectionFactory" ref="connectionFactory"/>
    <property name="destination" ref="topicDestination"/>
    <property name="messageListener" ref="topicMessageListener2"/>
    <!-- 消息持久化 -->
    <property name="subscriptionDurable" value="true"/>
    <!-- 消费者标识 -->
    <property name="clientId" value="topic-consumer-b"/>
    <!-- 订阅者标识(与消费者标识符可以不一样;默认为监听器全限定名) -->
    <property name="durableSubscriptionName" value="topic-consumer-b"/>
    <!-- 设置为发布/订阅模式 -->
    <property name="pubSubDomain" value="true"/>
    <!-- 是否开启事务 -->
    <property name="sessionTransacted" value="false"/>
    <!-- 客户端消息确认模式名称 -->
    <property name="sessionAcknowledgeModeName" value="CLIENT_ACKNOWLEDGE"/>
</bean>

三、创建消费者2监听器类  

TopicMessageListener2.java
package cn.itcast.activemq.spring.topic;
import javax.jms.JMSException;
import javax.jms.Message;
import javax.jms.MessageListener;
import javax.jms.Session;
import javax.jms.TextMessage;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.jms.listener.adapter.AbstractAdaptableMessageListener;

public class TopicMessageListener2 extends AbstractAdaptableMessageListener {

   @Override
   public void onMessage(Message message, Session session) throws JMSException {
      // 判断消息类型是TextMessage
      if (message instanceof TextMessage) {
         // 如果是,则进行强转
         TextMessage textMessage = (TextMessage) message;
         try {
            // 消费消息,打印消息内容
            String text = textMessage.getText();
            System.out.println("TopicMessageListener2-消费者2消息监听器接收到消息;消息内容为:" + text);
         } catch (Exception e) {
            e.printStackTrace();
         }
         /**
          * 在spring的配置文件配置监听容器的时候如果 AcknowledgeMode配置为CLIENT_ACKNOWLEDGE的话:
          * 那么在监听器代码中抛出异常或者执行session.recover();则会将信息重新发送6次(默认每秒发一个消息)
          * 在重发6次后消息还是处理失败,那么消息将自动到DLQ-死信队列(Dead Letter Queue用来保存处理失败或者过期的消息;
          * 默认在ActiveMQ队列里面的名称为:ActiveMQ.DLQ)
          */
         session.recover();
         
         /**
          * 什么时候会重发:
          * Messages are redelivered to a client when any of the following occurs:
         
             A transacted session is used and rollback() is called.
             A transacted session is closed before commit() is called.
             A session is using CLIENT_ACKNOWLEDGE and Session.recover() is called.
          */
      }
   }
}

四、创建消费者1监听器类

TopicMessageListener1.java
package cn.itcast.activemq.spring.topic;

import javax.jms.JMSException;
import javax.jms.Message;
import javax.jms.MessageListener;
import javax.jms.Session;
import javax.jms.TextMessage;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.jms.listener.adapter.AbstractAdaptableMessageListener;

public class TopicMessageListener1 extends AbstractAdaptableMessageListener {

   @Override
   public void onMessage(Message message, Session session) throws JMSException {
      // 判断消息类型是TextMessage
      if (message instanceof TextMessage) {
         // 如果是,则进行强转
         TextMessage textMessage = (TextMessage) message;
         try {
            // 消费消息,打印消息内容
            String text = textMessage.getText();
            System.out.println("TopicMessageListener1-消费者1 消息监听器接收到消息;消息内容为:" + text);
         } catch (Exception e) {
            e.printStackTrace();
         }
      }
   }
}

五、创建测试生产者类

Producer.java
package cn.itcast.activemq.spring.topic;

import javax.jms.Destination;
import javax.jms.JMSException;
import javax.jms.Message;
import javax.jms.Session;
import javax.jms.TextMessage;

import org.apache.activemq.command.ActiveMQTextMessage;
import org.apache.activemq.command.ActiveMQTopic;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.jms.core.JmsTemplate;
import org.springframework.jms.core.MessageCreator;

public class Producer {

   public static void main(String[] args) {
      // 创建spring容器
      ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext-activemq-topic-producer.xml");

      // 从spring容器中获取JMSTemplate,这个对象是用于发送消息的
      JmsTemplate jmsTemplate = context.getBean(JmsTemplate.class);

      //创建消息模式
      Destination destination = (Destination)context.getBean("topicDestination");
      
      // 使用JMSTemplate发送消息
      jmsTemplate.send(destination, new MessageCreator() {

         @Override
         public Message createMessage(Session session) throws JMSException {
            TextMessage textMessage = new ActiveMQTextMessage();
            textMessage.setText("。---spring-topic的方式发送。订阅主题的名称为:topic.item");

            System.out.println("已发送消息...");

            return textMessage;
         }
      });
   }
}

六、分别创建消费者测试类1、2

package cn.itcast.activemq.spring.topic;

import org.springframework.context.support.ClassPathXmlApplicationContext;

public class Consumer1 {

   public static void main(String[] args) {
      // 创建spring容器
      new ClassPathXmlApplicationContext("applicationContext-activemq-topic-consumer1.xml");
   }

}
package cn.itcast.activemq.spring.topic;

import org.springframework.context.support.ClassPathXmlApplicationContext;

public class Consumer2 {

   public static void main(String[] args) {
      // 创建spring容器
      new ClassPathXmlApplicationContext("applicationContext-activemq-topic-consumer2.xml");
   }

}

 

测试效果:

猜你喜欢

转载自blog.csdn.net/m0_46405589/article/details/115086360