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!");
    }
}
相关推荐
你想考研啊3 天前
Linux下搭建Activemq的Master-Slave(共享文件模式)
linux·运维·activemq
好玩的Matlab(NCEPU)7 天前
消息队列RabbitMQ、Kafka、ActiveMQ 、Redis、 ZeroMQ、Apache Pulsar对比和如何使用
kafka·rabbitmq·activemq
埃泽漫笔12 天前
Kafka、ActiveMQ、RabbitMQ、RocketMQ 对比
kafka·rabbitmq·activemq
小池先生1 个月前
activemq延迟消息变成实时收到了?
linux·数据库·activemq
clownAdam2 个月前
ActiveMQ classic ,artemis ,artemis console ,nms clients,cms client详解
activemq
百思可瑞教育2 个月前
ActiveMQ、RocketMQ、RabbitMQ、Kafka 的全面对比分析
vue.js·分布式·rabbitmq·rocketmq·activemq·北京百思可瑞教育·百思可瑞教育
Zhang.jialei3 个月前
HiveMQ 2024.9 设计与开发文档
hive·物联网·activemq
学习HCIA的小白5 个月前
ActiveMQ
activemq
代码的余温5 个月前
ActiveMQ多消费者负载均衡优化指南
java·后端·负载均衡·activemq
计算机毕设定制辅导-无忧学长6 个月前
ActiveMQ 高级特性:延迟消息与优先级队列实战(一)
activemq