ActiveMQ学习笔记(一)—— 队列

能干嘛?
解耦:系统间不直接调用,代码改动少,如A发送json给B,A发送xml给C,在接入D系统的时候又要发送其他格式的数据
削峰:控制并发流量,不直接请求我,当我处理完了才会去中间人取下一个请求
异步:不需要立即响应,减少等待时间

发送消息

package cn.fg.jsm.producer;

import javax.jms.Connection;
import javax.jms.JMSException;
import javax.jms.MessageProducer;
import javax.jms.Queue;
import javax.jms.Session;
import javax.jms.TextMessage;

import org.apache.activemq.ActiveMQConnectionFactory;

//消息生产者
public class Producer {

	public static void main(String[] args) throws JMSException {
		//1.创建连接工厂,brokerURL(可以理解为实例):ActiveMQ实例的地址
		ActiveMQConnectionFactory factory = new ActiveMQConnectionFactory("tcp://192.168.1.3:61616");
		
		//2.通过工厂创建连接
		Connection connection = factory.createConnection();
		connection.start(); //开始连接
		
		//3.创建回话,两个参数:transacted 事务,acknowledgeMode 签收
		Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
		
		//4.创建目的地(队列或主题)
		//Destination destination = session.createQueue("queue01"); //Destination 是接口 Queue、Topic 继承Destination
		Queue queue = session.createQueue("queue01");  //创建队列
		//Topic topic = session.createTopic("topic01");  //创建主题
		
		//5.创建消息生产者,参数:destination 目的地
		MessageProducer messageProducer = session.createProducer(queue);
		messageProducer.setDeliveryMode(DeliveryMode.PERSISTENT);  //发送的消息是持久的或非持久的;默认持久的;
		//messageProducer.setDeliveryMode(DeliveryMode.NON_PERSISTENT); //非持久
		//messageProducer.setTimeToLive(0); //过期时间
		//......省略其他set方法;这里是生产着的全局配置,如果想某一条消息有不一样的配置,详见下方针对Message的配置
		
		//6.创建消息
		TextMessage textMessage = session.createTextMessage("这是一个消息" + System.currentTimeMillis());

		//消息头常用属性
		//Message message = null; //Message是所有消息的父接口,下面这些属性是针对某一条消息的设置
		//message.setJMSDestination(destination); 消息目的地,即Queue或Topic,可以给每个消息指定不同的目的地
		//DeliveryMode:消息持久或非持久模式,默认持久,当mq服务器出现故障时,消息不会丢;恢复后可以再次传递消息(前提是消息已经发送到mq,只是没被消费就宕机了)
		//message.setJMSDeliveryMode(DeliveryMode.PERSISTENT);   //持久,如果mq宕机,再次启动后,管理台Messages Enqueued会为0,但是Number Of Pending Messages仍然存在
		//message.setJMSDeliveryMode(DeliveryMode.NON_PERSISTENT); //非持久,如果mq宕机,再次启动后,所有数据都是0
		//message.setJMSExpiration(0);  消息过期时间,毫秒;默认0,永不过期;达到过期时间后,仍未到达目的地,则消息会被清除;
		//message.setJMSPriority(4);  消息优先级,0-9十个级别,默认4;0-4表示普通,5-9表示加急,数字越高不代表越早达到,但是加急一定比普通优先到达目的地
		//message.setJMSMessageID(id);  //消息唯一id,默认由mq生成
		
		//消息属性,用于识别、去重、重点标注等操作
		//message.setStringProperty("flag", "vip");
		//message.setBooleanProperty("isMan", true);
		//message.getStringProperty("flag");
		
		//五类消息体,即消息的数据;常用TextMessage、MapMessage,发送消息体和接收消息必须是一致的,如用TextMessage发送就要用TextMessage接收
		//TextMessage textMessage = session.createTextMessage(); //字符串消息
		//MapMessage mapMessage = session.createMapMessage(); //map类消息 key为String类型,value为基本数据类型
		//mapMessage.setString("msg", "这是一个消息");
		//mapMessage.setDouble("price", 100L);
		//mapMessage.getString(name)
		//BytesMessage bytesMessage = session.createBytesMessage(); //二进制数组消息,byte[]
		//StreamMessage streamMessage = session.createStreamMessage(); //数据流消息
		//ObjectMessage objectMessage = session.createObjectMessage(); //对象消息,可序列化的java对象
		
		//7.发送消息
		messageProducer.send(textMessage);
		//messageProducer.send(destination, message, deliveryMode, priority, timeToLive); 发送消息,方法重载
		
		//8.释放资源
		messageProducer.close();
		session.close();
		connection.close();
		
		System.out.println("消息发送完毕");
	}
}

访问管理控制台

接收消息(阻塞)

package cn.fg.jsm.producer;

import javax.jms.Connection;
import javax.jms.Destination;
import javax.jms.JMSException;
import javax.jms.Message;
import javax.jms.MessageConsumer;
import javax.jms.MessageProducer;
import javax.jms.Queue;
import javax.jms.Session;
import javax.jms.TextMessage;

import org.apache.activemq.ActiveMQConnectionFactory;

//消息消费者
public class Consumer {

	public static void main(String[] args) throws JMSException {
		//1.创建连接工厂,brokerURL(可以理解为实例):ActiveMQ实例的地址
		ActiveMQConnectionFactory factory = new ActiveMQConnectionFactory("tcp://192.168.1.3:61616");
		
		//2.通过工厂创建连接
		Connection connection = factory.createConnection();
		connection.start(); //开始连接
		
		//3.创建回话,两个参数:transacted 事务,acknowledgeMode 签收
		Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
		
		//4.创建目的地(队列或主题)
		//Destination destination = session.createQueue("queue01"); //Destination 是接口 Queue、Topic 继承Destination
		Queue queue = session.createQueue("queue01");  //创建队列
		//Topic topic = session.createTopic("topic01");  //创建主题
		
		//5.创建消费者,参数:destination 目的地
		MessageConsumer messageConsumer = session.createConsumer(queue);
		
		//6.接收消息,同步阻塞
		while (true) {
			//接收消息,返回Message接口,这里使用TextMessage,因为发送消息使用的是TextMessage
			//TextMessage textMessage = (TextMessage) messageConsumer.receive();  //这个方法将一直等待,当有消息了才会执行下面的方法,每次获取一条消息
			TextMessage textMessage = (TextMessage) messageConsumer.receive(10000); //只等10秒钟,没有消息来我就执行下面的代码了
			if (textMessage != null) {
				System.out.println(textMessage.getText());
			} else {
				break;
			}
		}
		
		//7.释放资源
		messageConsumer.close();
		session.close();
		connection.close();
		
	}
}

访问管理控制台 

使用监听器接收消息 (非阻塞)

package cn.fg.jsm.listener;

import java.io.IOException;

import javax.jms.Connection;
import javax.jms.JMSException;
import javax.jms.Message;
import javax.jms.MessageConsumer;
import javax.jms.MessageListener;
import javax.jms.Queue;
import javax.jms.Session;
import javax.jms.TextMessage;

import org.apache.activemq.ActiveMQConnectionFactory;

public class Listener {

	public static void main(String[] args) throws JMSException, IOException {
		//1.创建连接工厂,brokerURL(可以理解为实例):ActiveMQ实例的地址
		ActiveMQConnectionFactory factory = new ActiveMQConnectionFactory("tcp://192.168.1.3:61616");
		
		//2.通过工厂创建连接
		Connection connection = factory.createConnection();
		connection.start(); //开始连接
		
		//3.创建回话,两个参数:transacted 事务,acknowledgeMode 签收
		Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
		
		//4.创建目的地(队列或主题)
		Queue queue = session.createQueue("queue01");  //创建队列
		
		//5.创建消费者,参数:destination 目的地
		MessageConsumer messageConsumer = session.createConsumer(queue);
		
		//6.创建监听器,MessageListener是一个接口,可以自己自定义监听类实现接口,这里就使用一个内部类演示
		messageConsumer.setMessageListener(new MessageListener() {
			@Override
			public void onMessage(Message message) {
				//消息到了之后的逻辑处理
				if (message != null && message instanceof TextMessage) {
					TextMessage textMessage = (TextMessage) message;
					try {
						System.out.println(textMessage.getText());
					} catch (JMSException e) {
						e.printStackTrace();
					}
				}
			}
		});
		
		//7.释放资源
		System.in.read(); //控制台按任意键继续,这里阻塞一下,如果关闭了资源,消息就收不到了
		messageConsumer.close();
		session.close();
		connection.close();
		
	}
}

如果有多个消费者同时接收同一个队列名称,则消费者会轮流接收到消息,例如生产者发送6条消息,消费者A收到135,消费者B收到246

总结

1、JMS开发步骤

2、 队列是点对点的消息传递,每个消息一般只设定被一个消费者接收,如果要被多个消费接收,就要使用主题了(后面介绍)

3、无论消费者是否在线,只要没有被消费,就会一直存在(可以登录控制台手动清除),但是一旦被消费就不会再次出现。

课外知识

activemq除了作为独立服务器运行外,还可以嵌入到java代码中,使应用程序本身携带mq的功能

		<!-- 首先要添加 jackson-databind-->
		<dependency>
		    <groupId>com.fasterxml.jackson.core</groupId>
		    <artifactId>jackson-databind</artifactId>
		    <version>2.9.8</version>
		</dependency>
	public static void main(String[] args) throws Exception {
		BrokerService brokerService = new BrokerService(); //new一个activemq的服务实例
		brokerService.addConnector("tcp://127.0.0.1:61616"); //添加一个连接器
		brokerService.start(); //一个嵌入式的activemq服务就运行起来了
	}
	//发送消息
	public static void main(String[] args) throws JMSException {
		//连接到本机的activemq
		ActiveMQConnectionFactory factory = new ActiveMQConnectionFactory("tcp://127.0.0.1:61616"); 
		Connection connection = factory.createConnection();
		connection.start(); 
		Session session = connection.createSession(false, Session.DUPS_OK_ACKNOWLEDGE);
		Queue queue = session.createQueue("queue01");  //创建队列
		MessageProducer messageProducer = session.createProducer(queue);
		TextMessage textMessage = session.createTextMessage("这是一个消息" + System.currentTimeMillis());
		messageProducer.send(textMessage);
		messageProducer.close();
		session.close();
		connection.close();
		System.out.println("消息发送完毕");
	}
发布了64 篇原创文章 · 获赞 0 · 访问量 3218

猜你喜欢

转载自blog.csdn.net/q42368773/article/details/102790318