Spring + ActiveMQ 整合实现发布/订阅(publish-subscribe)消息发送案例

本节演示发布/订阅(publish-subscribe)模式的消息发送的 Spring + ActiveMQ 代码。

1、生产者代码
  • spring 关键代码:springContext-activemq.xml
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">


  <!-- 创建一个ConnectionFactory,为了提升性能用了连接池 -->
  <bean id="connectionFactory" 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</value>
        </property>
      </bean>
    </property>
    <property name="maxConnections" value="50" />
  </bean>


  <!-- 创建消息目的地,constructor-arg是目的地的名称,此处为spring-topic -->
  <bean id="destinationTopic" class="org.apache.activemq.command.ActiveMQTopic">
    <constructor-arg index="0" value="spring-topic" />
  </bean>


  <!-- 构建JmsTemplate -->
  <bean id="jmsTemplate" class="org.springframework.jms.core.JmsTemplate">
    <property name="connectionFactory" ref="connectionFactory" />
    <property name="defaultDestination" ref="destinationTopic" />
    <property name="messageConverter">
      <bean
        class="org.springframework.jms.support.converter.SimpleMessageConverter" />
    </property>
  </bean>


</beans>

生产者关键代码:SpringTopicSender

swift 复制代码
package producer;


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


import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.jms.core.JmsTemplate;
import org.springframework.jms.core.MessageCreator;


/**
 * 发布/订阅(publish-subscribe)消息发送,spring整合
 * 
 * @author JPM
 */
public class SpringTopicSender {
  public static void main(String[] args) {


    ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext(
        "classpath:spring/springContext-activemq.xml");
    JmsTemplate jmsTemplate = (JmsTemplate) context.getBean("jmsTemplate");
    jmsTemplate.send(new MessageCreator() {


      public Message createMessage(Session session) throws JMSException {
        TextMessage message = session.createTextMessage();
        message.setText("hello,spring-topic!");
        return message;
      }
    });
    context.close();
  }
}

运行 SpringTopicSender 类,查看 ActiveMQ 管理界面

说明已经发布了一个主题消息。

2、消费者代码(receive 方法获取消息)
  • spring 关键代码:springContext-activemq.xml
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">


  <bean id="connectionFactory" 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</value>
        </property>
      </bean>
    </property>
    <property name="maxConnections" value="50" />
  </bean>


  <bean id="destinationTopic" class="org.apache.activemq.command.ActiveMQTopic">
    <constructor-arg index="0" value="spring-topic" />
  </bean>


  <bean id="jmsTemplate" class="org.springframework.jms.core.JmsTemplate">
    <property name="connectionFactory" ref="connectionFactory" />
    <property name="defaultDestination" ref="destinationTopic" />
    <property name="messageConverter">
      <bean
        class="org.springframework.jms.support.converter.SimpleMessageConverter" />
    </property>
  </bean>


</beans>

消费者关键代码:SpringTopicReceiver1 和 SpringTopicReceiver2

typescript 复制代码
package consumer;


import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.jms.core.JmsTemplate;


/**
 * 发布/订阅(publish-subscribe)消息接收1,spring整合
 * 
 * @author JPM
 */
public class SpringTopicReceiver1 {


  public static void main(String[] args) {
    ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext(
        "classpath:spring/springContext-activemq.xml");
    JmsTemplate jmsTemplate = (JmsTemplate) context.getBean("jmsTemplate");
    String message = (String) jmsTemplate.receiveAndConvert();
    System.out.println("SpringTopicReceiver1--->" + message);
    context.close();
  }
}
typescript 复制代码
package consumer;


import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.jms.core.JmsTemplate;


/**
 * 发布/订阅(publish-subscribe)消息接收2,spring整合
 * 
 * @author JPM
 */
public class SpringTopicReceiver2 {


  public static void main(String[] args) {
    ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext(
        "classpath:spring/springContext-activemq.xml");
    JmsTemplate jmsTemplate = (JmsTemplate) context.getBean("jmsTemplate");
    String message = (String) jmsTemplate.receiveAndConvert();
    System.out.println("SpringTopicReceiver2--->" + message);
    context.close();
  }
}

运行 SpringTopicReceiver1 和 SpringTopicReceiver2 类,查看控制台和 ActiveMQ 管理界面

说明2个消费者已经启动,但是看控制台输出都是空的,说明没有消费到消息,原因是对于 topic 消息来说,消费者必须先启动,订阅了主题,然后才能收到主题发来的消息。我们刚才是先发送的主题消息,后启动的消费者,因此2个消费者都没有输出。

下面我们再通过刚才的生产者 SpringTopicSender 类发送一个主题消息,观察消费者的控制台和 ActiveMQ 管理界面的变化

说明,2个消费者都获取到了主题消息。

3、消费者代码(使用消息监听器获取消息)

spring 关键代码 springContext-activemq1.xml

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">


  <bean id="connectionFactory" 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</value>
        </property>
      </bean>
    </property>
    <property name="maxConnections" value="50" />
  </bean>


  <bean id="destinationTopic" class="org.apache.activemq.command.ActiveMQTopic">
    <constructor-arg index="0" value="spring-topic" />
  </bean>


  <bean id="jmsContainer1"
    class="org.springframework.jms.listener.DefaultMessageListenerContainer">
    <property name="connectionFactory" ref="connectionFactory" />
    <property name="destination" ref="destinationTopic" />
    <property name="messageListener" ref="messageListener1" />
  </bean>


  <bean id="messageListener1" class="consumer.SpringTopicListener1" />


</beans>

springContext-activemq2.xml

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">


  <bean id="connectionFactory" 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</value>
        </property>
      </bean>
    </property>
    <property name="maxConnections" value="50" />
  </bean>


  <bean id="destinationTopic" class="org.apache.activemq.command.ActiveMQTopic">
    <constructor-arg index="0" value="spring-topic" />
  </bean>


  <bean id="jmsContainer2"
    class="org.springframework.jms.listener.DefaultMessageListenerContainer">
    <property name="connectionFactory" ref="connectionFactory" />
    <property name="destination" ref="destinationTopic" />
    <property name="messageListener" ref="messageListener2" />
  </bean>


  <bean id="messageListener2" class="consumer.SpringTopicListener2" />


</beans>

消费者关键代码 SpringTopicListener1

java 复制代码
package consumer;


import java.io.IOException;


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


import org.springframework.context.support.ClassPathXmlApplicationContext;


/**
 * 发布/订阅(publish-subscribe)消息接收1,spring整合,使用Listener
 * 
 * @author JPM
 */
public class SpringTopicListener1 implements MessageListener {


  public void onMessage(Message message) {
    String msg = null;
    try {
      msg = ((TextMessage) message).getText();
    } catch (JMSException e) {
      e.printStackTrace();
    }
    System.out.println("SpringTopicListener1--->" + msg);
  }


  public static void main(String[] args) {
    ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext(
        "classpath:spring/springContext-activemq1  .xml");
    try {
      System.in.read();
    } catch (IOException e) {
      e.printStackTrace();
    }
    context.close();
  }


}

SpringTopicListener2

java 复制代码
package consumer;


import java.io.IOException;


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


import org.springframework.context.support.ClassPathXmlApplicationContext;


/**
 * 发布/订阅(publish-subscribe)消息接收2,spring整合,使用Listener
 * 
 * @author JPM
 */
public class SpringTopicListener2 implements MessageListener {


  public void onMessage(Message message) {
    String msg = null;
    try {
      msg = ((TextMessage) message).getText();
    } catch (JMSException e) {
      e.printStackTrace();
    }
    System.out.println("SpringTopicListener2--->" + msg);
  }


  public static void main(String[] args) {
    ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext(
        "classpath:spring/springContext-activemq2.xml");
    try {
      System.in.read();
    } catch (IOException e) {
      e.printStackTrace();
    }
    context.close();
  }


}

运行 SpringTopicListener1 和 SpringTopicListener2 类,查看 ActiveMQ 管理界面

成功启动一个消费者

成功启动第二个消费者。

首先运行刚才的生产者 SpringTopicSender 类发送一条主题消息,查看 ActiveMQ 管理界面

说明消费了主题消息。

查看 SpringTopicListener1 和 SpringTopicListener2 的控制台

从控制台来看,两个订阅者都获取到了生产者发布的消息。

相关推荐
AI人H哥会Java1 小时前
【Spring】Spring的模块架构与生态圈—Spring MVC与Spring WebFlux
java·开发语言·后端·spring·架构
小马爱打代码2 小时前
SpringCloud(注册中心+OpenFeign+网关+配置中心+服务保护+分布式事务)
分布式·spring·spring cloud
毕设资源大全2 小时前
基于SpringBoot+html+vue实现的林业产品推荐系统【源码+文档+数据库文件+包部署成功+答疑解惑问到会为止】
java·数据库·vue.js·spring boot·后端·mysql·html
Watermelon_Mr2 小时前
Spring(三)-SpringWeb-概述、特点、搭建、运行流程、组件、接受请求、获取请求数据、特殊处理、拦截器
java·后端·spring
eternal__day2 小时前
数据结构十大排序之(冒泡,快排,并归)
java·数据结构·算法
唐墨1232 小时前
golang自定义MarshalJSON、UnmarshalJSON 原理和技巧
开发语言·后端·golang
凡人的AI工具箱2 小时前
每天40分玩转Django:Django测试
数据库·人工智能·后端·python·django·sqlite
qyq12 小时前
Django框架与ORM框架
后端·python·django
Theodore_10223 小时前
3 需求分析
java·开发语言·算法·java-ee·软件工程·需求分析·需求
小笨猪-3 小时前
统⼀服务⼊⼝-Gateway
java·spring cloud·微服务·gateway