ActiveMQ

Queue与Topic比较

发送消息

java 复制代码
public class Sender{
	
	public static void main(String[] args){
	
		Sender sender = new Sender();
		
		String msg = "Hello World!";
		
		sender.sendMessage(msg);
		System.out.println("发送消息结束:" + msg);
	}

	public void sendMessage(String msg){
		
		String user = ActiveMQConnection.DEFAULT_USER;
		String password = ActiveMQConnection.DEFAULT_PASSWORD;

		String url = AcbiveMQConnection.DEFAULT_BROKER_URL;
		String subject = "TOOL.DEFAULT";

		//1.初始化连接工厂
		ConnectionFactory contectionFactory = new ActiveMQConnectionFactory(user, password, url);
		try{
			//2.创建连接
			Connection connection = contectionFactory.createConnection();
			connection.start();

			//3.创建会话
			Session session = connection.createSession(Boolean.TRUE, Session.AUTO_ACKNOWLEDGE);
			//4.打开队列
			Destination destination = session.createQueue(subject);

			//5. MessageProducer负责发送消息
			MessageProducer producer = session.createProducer(destination);
			TextMessage message = session.createTextMessage();

			for(int i = 0;i < 10;i++){
				String tmp = i + ":" + msg;
				message.setStringProperty("hello",tmp);

				//6.发送消息
				producer.send(message);
				System.out.println("send:" + tmp);
				Thread.sleep(3000);
				//只有在commit之后,消息才会进入队列
				session.commit();

				//7.关闭会话和连接
				session.close();
				conneciton.close();
			}
		}catch(JMSException e){
			e.printStackTrace();
		}catch(InterruptedException e){
			e.printStackTrace();
		}
	}
}

通过Queue接收消息

java 复制代码
public class Receiver{
	
	public static void main(String[] args){
		String user = ActiveMQConnection.DEFAULT_USER;
	    String password = ActiveMQConnection.DEFAULT_PASSWORD;
	    String url = ActiveMQConnection.DEFAULT_BROKER_URL;
	    String subject = "TOOL.DEFAULT";

		ConnectionFactory connectionFactory = new ActiveMQConnectionFactory(user, password, url);
		Connection connection;
		try{
			connection = connectionFactory.createConnection();
      		connection.start();

			final Session session = connection.createSession(Boolean.TRUE, Session.AUTO_ACKNOWLEDGE);
			Destination destination = session.createQueue(subject);

			// MessageConsumer负责接受消息
			MessageConsumer consumer = session.createConsumer(destination);
			consumer.setMessageListener(new MessageListener(){
				
				public void onMessage(Message msg){
					TextMessage message = (TextMessage)msg;
					try{
						String hello = message.getStringProperty("hello");
            			System.out.println("收到消息:\t" + hello);
            			session.commit();
					}catch(JMSException e){
						e.printStackTrace();
					}
				}
			});
			session.close();
			connection.close();
		}catch(JMSException e){
			e.printStackTrace();
		}
	}
}

通过Topic发布消息

java 复制代码
public class Publisher{
	
	public static void main(String[] args){
		Publisher pb = new Publisher();
    	String msg = "Hello World!~~~~~";
    	pb.sendMessage(msg);
    	System.out.println("发送消息结束:" + msg);
	}

	public void sendMessage(String msg){
		
		String user = ActiveMQConnection.DEFAULT_USER;
    	String password = ActiveMQConnection.DEFAULT_PASSWORD;

		String url = ActiveMQConnection.DEFAULT_BROKER_URL;
    	String subject = "MQ.TOPIC";

		ConnectionFactory contectionFactory = new ActiveMQConnectionFactory(user, password, url);
		try{
			Connection connection = contectionFactory.createConnection();
      		connection.start();
      		Session session = connection.createSession(Boolean.TRUE, Session.AUTO_ACKNOWLEDGE);
			
			//创建要发布的主题,和Queue的区别就在此
			Destination destination = session.createTopic(subject);
			MessageProducer producer = session.createProducer(destination);
			TextMessage message = session.createTextMessage();
      		message.setStringProperty("hello", msg);

			producer.send(message);//发送消息

			session.commit();
		    session.close();
		    connection.close();
		}catch(JMSException e){
			e.printStackTrace();
		}
	}
}

通过Topic订阅消息

java 复制代码
public class Subscriber{
	
	public static void main(String[] args){
		String user = ActiveMQConnection.DEFAULT_USER;
	    String password = ActiveMQConnection.DEFAULT_PASSWORD;
	    String url = ActiveMQConnection.DEFAULT_BROKER_URL;
	    String subject = "MQ.TOPIC";
	    
	    ConnectionFactory connectionFactory = new ActiveMQConnectionFactory(user, password, url);
	    Connection connection;
	    try{
	    	connection = connectionFactory.createConnection();
	        connection.start();
	        final Session session = connection.createSession(Boolean.TRUE, Session.AUTO_ACKNOWLEDGE);
	        Topic topic = session.createTopic(subject);
	        // MessageConsumer负责接受消息
	        MessageConsumer consumer = session.createConsumer(topic);
	        consumer.setMessageListener(new MessageListener(){
	        	
	        	public void onMessage(Message msg) {
	        	
		          TextMessage message = (TextMessage) msg;
		          try {
		            String hello = message.getStringProperty("hello");
		            System.out.println("订阅者---SecondSubscriber---收到消息:\t" + hello);
		            session.commit();
		          } catch (JMSException e) {
		            e.printStackTrace();
		          }
		        }
	        });
	        session.close();
	        connection.close();
	    }catch(JMSException e){
	    	e.printStackTrace();
	    }
	}
}

Spring JMS收发消息

一、依赖

xml 复制代码
<dependency>
		<groupId>junit</groupId>
		<artifactId>junit</artifactId>
		<version>4.12</version>
		<scope>test</scope>
	</dependency>
	<dependency>
		<groupId>org.apache.activemq</groupId>
		<artifactId>activemq-all</artifactId>
		<version>5.11.0</version>
	</dependency>
	<dependency>
		<groupId>org.springframework</groupId>
		<artifactId>spring-jms</artifactId>
		<version>4.1.4.RELEASE</version>
	</dependency>
	<dependency>  
        <groupId>org.springframework</groupId>  
        <artifactId>spring-test</artifactId>  
        <version>4.1.4.RELEASE</version>  
    </dependency> 

二、队列(Queue)消息的收发

点对点消息,如果没有消费者在监听队列,消息将保留在队列中,直至消息消费者连接到队列为止。

在此模型中,消息不是自动推动给消息消费者的,而是要由消息消费者从队列中请求获得(拉模式)

①、配置文件

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

	<!-- 配置JMS连接工厂 -->
	<bean id="connectionFactory" class="org.apache.activemq.ActiveMQConnectionFactory">
		<property name="brokerURL" value="failover:(tcp://localhost:61616)" />
	</bean>
	
	<!-- 定义消息队列(Queue) -->
	<bean id="queueDestination" class="org.apache.activemq.command.ActiveMQQueue">
		<!-- 设置消息队列的名字 -->
		<constructor-arg>
			<value>queue1</value>
		</constructor-arg>
	</bean>
	
	<!-- 配置JMS模板(Queue),Spring提供的JMS工具类,它发送、接收消息。 -->
	<bean id="jmsTemplate" class="org.springframework.jms.core.JmsTemplate">
		<property name="connectionFactory" ref="connectionFactory" />
		<property name="defaultDestination" ref="queueDestination" />
		<property name="receiveTimeout" value="10000" />
	</bean>
	
	<!--queue消息生产者 -->
	<bean id="producerService" class="com.yoodb.mq.queue.ProducerServiceImpl">
		<property name="jmsTemplate" ref="jmsTemplate"></property>
	</bean>

	<!--queue消息消费者 -->
	<bean id="consumerService" class="com.yoodb.mq.queue.ConsumerServiceImpl">
		<property name="jmsTemplate" ref="jmsTemplate"></property>
	</bean>
</beans>

②、消息生产者

java 复制代码
public class ProducerServiceImpl implements ProducerService{
	
	private JmsTemplate jmsTemplate;

	//向指定队列发送消息
	public void sendMessage(Destination destination,final Stringmsg){
		
		System.out.println("向队列" + destination.toString() + "发送了消息___" + msg);
		jmsTemplate.send(destination,new MessageCreator(){
			public Message createMessage(Session session)throws JMSException{
				return session.createTextMessage(msg);
			}
		});
	}

	//向默认队列发送消息
	publc void sendMessage(final String msg){
		String destination =  jmsTemplate.getDefaultDestination().toString();
		System.out.println("向队列" +destination+ "发送了消息___" + msg);

		jmsTemplate.send(new MessageCreator(){
			public Message createMesssage(Session session)throws JMSException{
				return session.createTextMessage(msg);
			}
		});
	}

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

③、消息消费者代码

java 复制代码
public class ConsumerServiceImpl implements ConsumerService{

	private JmsTemplate jsmTemplate;

	//接收消息
	public void receive(Destination destination){
		TextMessage tm = (TextMessage)jmsTemplate.receive(destination);
		try{
			System.out.println("从队列" + destination.toString() + "收到消息" + tm.getText());	
		}catch(JMSException e){
			e.printStackTrace();
		}
	}

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

队列消息监听,在接受消息的时候,可以不用消息消费者代码的方式,Spring JMS同样提供了消息监听的模式,对应的配置和代码内容。

xml 复制代码
<!-- 定义消息队列(Queue),我们监听一个新的队列,queue2 -->
<bean id="queueDestination2" class="org.apache.activemq.command.ActiveMQQueue">
	<!-- 设置消息队列的名字 -->
	<constructor-arg>
		<value>queue2</value>
	</constructor-arg>
</bean>

<!-- 配置消息队列监听者(Queue),代码下面给出,只有一个onMessage方法 -->
<bean id="queueMessageListener" class="com.yoodb.mq.queue.QueueMessageListener" />

<!-- 消息监听容器(Queue),配置连接工厂,监听的队列是queue2,监听器是上面定义的监听器 -->
<bean id="jmsContainer"
	class="org.springframework.jms.listener.DefaultMessageListenerContainer">
	<property name="connectionFactory" ref="connectionFactory" />
	<property name="destination" ref="queueDestination2" />
	<property name="messageListener" ref="queueMessageListener" />
</bean>
java 复制代码
public class QueueMessageListener implements MessageListener{
	
	//当收到信息时,自动调用该方法
	public void onMessage(Message message){
		TextMessage tm = (TextMessage) message;
		try{
			System.out.println("ConsumerMessageListener收到了文本消息:\t"
					+ tm.getText());
		}catch(JMSException e){
			e.printStackTrace();
		}
	}
}

三、主题(Topic)消息收发

使用Spring JMS的时候,主题[订阅/发布](Topic)和队列消息模式的主要差异体现在JmsTemplate中"pubSubDomain"是否设置为True

如果为True,则是Topic;如果是false或者默认,则是Queue

①、配置文件

xml 复制代码
<!-- 定义消息主题(Topic) -->
<bean id="topicDestination" class="org.apache.activemq.command.ActiveMQTopic">
    <constructor-arg>
    <value>guo_topic</value>
    </constructor-arg>
</bean>

<!-- 配置JMS模板(Topic),pubSubDomain="true"-->
<bean id="topicJmsTemplate" class="org.springframework.jms.core.JmsTemplate">
    <property name="connectionFactory" ref="connectionFactory" />
    <property name="defaultDestination" ref="topicDestination" />
    <property name="pubSubDomain" value="true" />
    <property name="receiveTimeout" value="10000" />
</bean>

<!--topic消息发布者 -->
<bean id="topicProvider" class="com.yoodb.mq.topic.TopicProvider">
    <property name="topicJmsTemplate" ref="topicJmsTemplate"></property>
</bean>

<!-- 消息主题监听者 和 主题监听容器 可以配置多个,即多个订阅者 -->
<!-- 消息主题监听者(Topic) -->
<bean id="topicMessageListener" class="com.yoodb.mq.topic.TopicMessageListener" />

<!-- 主题监听容器 (Topic) -->
<bean id="topicJmsContainer"
    class="org.springframework.jms.listener.DefaultMessageListenerContainer">
    <property name="connectionFactory" ref="connectionFactory" />
    <property name="destination" ref="topicDestination" />
    <property name="messageListener" ref="topicMessageListener" />
</bean>

②、消息发布者

java 复制代码
public class TopicProvider {
    private JmsTemplate topicJmsTemplate;
    /**
     * 向指定的topic发布消息
     * 
     * @param topic
     * @param msg
     */
    public void publish(final Destination topic, final String msg) {
        topicJmsTemplate.send(topic, new MessageCreator() {
        public Message createMessage(Session session) throws JMSException {
            System.out.println("topic name 是" + topic.toString()
            + ",发布消息内容为:\t" + msg);
            return session.createTextMessage(msg);
        }
    });
    }
    public void setTopicJmsTemplate(JmsTemplate topicJmsTemplate) {
        this.topicJmsTemplate = topicJmsTemplate;
    }
}

③、消息订阅者(监听)

java 复制代码
public class TopicMessageListener implements MessageListener {
    public void onMessage(Message message) {
        TextMessage tm = (TextMessage) message;
        try {
            System.out.println("TopicMessageListener \t" + tm.getText());
        } catch (JMSException e) {
            e.printStackTrace();
        }
    }
}

测试代码

java 复制代码
/**
 * 测试Spring JMS
 * 
 * 1.测试生产者发送消息
 * 
 * 2. 测试消费者接受消息
 * 
 * 3. 测试消息监听
 * 
 * 4.测试主题监听
 *
 */
@RunWith(SpringJUnit4ClassRunner.class)
// ApplicationContext context = new
// ClassPathXmlApplicationContext("applicationContext.xml");
@ContextConfiguration("/applicationContext.xml")
public class SpringJmsTest {
    /**
     * 队列名queue1
     */
    @Autowired
    private Destination queueDestination;
    
    /**
     * 队列名queue2
     */
    @Autowired
    private Destination queueDestination2;
    
    /**
     * 主题 guo_topic
     */
    @Autowired
    @Qualifier("topicDestination")
    private Destination topic;
    
    /**
     * 主题消息发布者
     */
    @Autowired
    private TopicProvider topicProvider;
    
    /**
     * 队列消息生产者
     */
    @Autowired
    @Qualifier("producerService")
    private ProducerService producer;
    
    /**
     * 队列消息生产者
     */
    @Autowired
    @Qualifier("consumerService")
    private ConsumerService consumer;
    
    /**
     * 测试生产者向queue1发送消息
     */
    @Test
    public void testProduce() {
    String msg = "Hello world!";
        producer.sendMessage(msg);
    }
    
    /**
     * 测试消费者从queue1接受消息
     */
    @Test
    public void testConsume() {
        consumer.receive(queueDestination);
    }
    
    /**
     * 测试消息监听
     * 
     * 1.生产者向队列queue2发送消息
     * 
     * 2.ConsumerMessageListener监听队列,并消费消息
     */
    @Test
    public void testSend() {
        producer.sendMessage(queueDestination2, "Hello China!!!");
    }
    
    /**
     * 测试主题监听
     * 1.生产者向主题发布消息
     * 2.ConsumerMessageListener监听主题,并消费消息
     */
    @Test
    public void testTopic() throws Exception {
        topicProvider.publish(topic, "Hello T-To-Top-Topi-Topic!");
    }
}
相关推荐
dvlinker9 天前
大数据技术Kafka详解 ① | 消息队列(Messages Queue)
大数据·kafka·rabbitmq·rocketmq·activemq·分布式发布订阅消息系统·messages queue
想学习java初学者12 天前
Docker compose部署Activemq
docker·容器·activemq
椰汁菠萝12 天前
docker运行ActiveMQ-Artemis
docker·容器·activemq
燃犀知不可乎骤得24 天前
如何在Linux环境中的Qt项目中使用ActiveMQ-CPP
linux·qt·activemq
燃犀知不可乎骤得24 天前
linux 运行 activemq,Linux 安装 ActiveMQ 服务器详解
linux·activemq
燃犀知不可乎骤得24 天前
Linux下安装ActiveMQ-CPP
c++·cms·activemq
小灰灰__1 个月前
Docker安装ActiveMQ镜像以及通过Java生产消费activemq示例
docker·activemq·java-activemq
Dylanioucn2 个月前
【分别为微服务云原生】9分钟ActiveMQ延时消息队列:定时任务的革命与Quartz的较量
微服务·云原生·activemq
空名_Noname2 个月前
【转载翻译】消息队列 - ActiveMQ、RabbitMQ、Kafka、ZeroMQ
c++·kafka·rabbitmq·activemq·zeromq
Dylanioucn2 个月前
【分布式微服务云原生】如何在ActiveMQ中优雅处理提前支付的延时订单
分布式·微服务·activemq