消息类型\事务消息\确认机制\应用场景\消息过滤\监听器接收
- 11 ActiveMQ消息类型
- 12 ActiveMQ事务消息和非事务消息
- 13 ActiveMQ消息确认机制
- 14 ActiveMQ消息持久化
- 15 MQ技术的应用场景
- 16 ActiveMQ消息过滤
- 17 ActiveMQ接收消息方式
11 ActiveMQ消息类型
1、TextMessage 文本消息:携带一个java.lang.String作为有效数据(负载)的消息,可用于字符串类型的信息交换;
2、ObjectMessage 对象消息:携带一个可以序列化的Java对象作为有效负载的消息,可用于Java对象类型的信息交换;
3、MapMessage 映射消息:携带一组键值对的数据作为有效负载的消息,有效数据值必须是Java原始数据类型(或者它们的包装类)及String。即:byte, short, int, long, float, double, char, boolean, String
4、BytesMessage 字节消息 :携带一组原始数据类型的字节流作为有效负载的消息;
5、StreamMessage 流消息:携带一个原始数据类型流作为有效负载的消息,它保持了写入流时的数据类型,写入什么类型,则读取也需要是相同的类型;
public class QueueSender {
public static final String BROKER_URL = "tcp://localhost:61616";
public static final String DESTINATION = "myQueue";
public static void main(String[] args) throws JMSException {
//1、创建连接工厂
ConnectionFactory connectionFactory = new ActiveMQConnectionFactory(BROKER_URL);
Connection connection = null;
Session session = null;
MessageProducer producer = null;
try {
//2、创建一个连接
connection = connectionFactory.createConnection();
//3、创建一个Session,第一个参数表示是否为事务消息,第二个参数表示消息确认方式
session = connection.createSession(Boolean.FALSE, Session.AUTO_ACKNOWLEDGE);
//4、创建消息
Order order = new Order();
order.setOrderId("123");
order.setName("订单");
order.setPrice("123.22");
Message message = session.createObjectMessage(order);
//5、消息目的地
Destination destination = session.createQueue(DESTINATION);
//6、消息生产者
producer = session.createProducer(destination);
//7、发送消息
producer.send(message);
} catch (Exception e) {
} finally {
connection.close();
producer.close();
session.close();
}
}
}
ublic class QueueReceiver {
public static final String BROKER_URL = "tcp://localhost:61616";
public static final String DESTINATION = "myQueue";
public static void main(String[] args) throws JMSException {
//1、创建连接工厂
ConnectionFactory connectionFactory = new ActiveMQConnectionFactory(BROKER_URL);
Connection connection = null;
Session session = null;
MessageConsumer messageConsumer = null;
try {
List<String> list = new ArrayList<>();
list.add("java.lang");
list.add("com.jms.type");
//必须设置对象中所有的字段所在的类是受信任的,对象类必须实现序列化接口
((ActiveMQConnectionFactory) connectionFactory).setTrustedPackages(list);
//2、创建一个连接
connection = connectionFactory.createConnection();
//接收消息多一个步骤:把连接启动
connection.start();
//3、创建一个Session,第一个参数表示是否为事务消息,第二个参数表示消息确认方式
session = connection.createSession(Boolean.FALSE, Session.AUTO_ACKNOWLEDGE);
//4、创建消息
Message message = session.createObjectMessage("Hello,ActiveMQ");
//5、消息目的地
Destination destination = session.createQueue(DESTINATION);
//6、消息消费者
messageConsumer = session.createConsumer(destination);
//7、接收消息:receive方法是一个阻塞方法,它会一直等待,直到接收到消息
// receive(Long 超时毫秒数) receiveNoWait()不等待
Message receiveMessage = messageConsumer.receive();
if (receiveMessage instanceof TextMessage) {
String text = ((TextMessage) message).getText();
System.out.println("接收到的消息为:" + text);
} else if (receiveMessage instanceof ObjectMessage) {
Order order = (Order) ((ObjectMessage) receiveMessage).getObject();
System.out.println(order.getOrderId());
System.out.println(order.getName());
System.out.println(order.getPrice());
}
} catch (Exception e) {
e.printStackTrace();
} finally {
connection.close();
messageConsumer.close();
session.close();
}
}
}
123
订单
123.22
Process finished with exit code 0
12 ActiveMQ事务消息和非事务消息
消息分为事务消息和非事务消息:
1、事务消息:创建会话Session使用transacted=true
connection.createSession(Boolean.TRUE, Session.AUTO_ACKNOWLEDGE);
2、非事务消息:创建会话Session使用transacted=false
connection.createSession(Boolean.FALSE, Session.AUTO_ACKNOWLEDGE);
事务消息必须在发送和接收完消息后显式地调用session.commit();
事务性消息,不管设置何种消息确认模式,都会自动被确认;
public class QueueSender {
public static final String BROKER_URL = "tcp://localhost:61616";
public static final String DESTINATION = "myQueue";
public static void main(String[] args) throws JMSException {
//1、创建连接工厂
ConnectionFactory connectionFactory = new ActiveMQConnectionFactory(BROKER_URL);
Connection connection = null;
Session session = null;
MessageProducer producer = null;
try {
//2、创建一个连接
connection = connectionFactory.createConnection();
//3、创建一个Session,第一个参数表示是否为事务消息,第二个参数表示消息确认方式
session = connection.createSession(Boolean.TRUE, Session.AUTO_ACKNOWLEDGE);
//4、创建消息
Message message = session.createTextMessage("Hello,ActiveMQ");
//5、消息目的地
Destination destination = session.createQueue(DESTINATION);
//6、消息生产者
producer = session.createProducer(destination);
//7、发送消息
producer.send(message);
//8、session会话需要提交事务,如果不提交消息不能发出,确认方式对事务型消息不起作用
session.commit();
} catch (Exception e) {
} finally {
producer.close();
session.close();
connection.close();
}
}
}
public class QueueReceiver {
public static final String BROKER_URL = "tcp://localhost:61616";
public static final String DESTINATION = "myQueue";
public static void main(String[] args) throws JMSException {
//1、创建连接工厂
ConnectionFactory connectionFactory = new ActiveMQConnectionFactory(BROKER_URL);
Connection connection = null;
Session session = null;
MessageConsumer messageConsumer = null;
try {
//2、创建一个连接
connection = connectionFactory.createConnection();
//接收消息多一个步骤:把连接启动
connection.start();
//3、创建一个Session,第一个参数表示是否为事务消息,第二个参数表示消息确认方式
session = connection.createSession(Boolean.TRUE, Session.AUTO_ACKNOWLEDGE);
//4、创建消息
Message message = session.createTextMessage("Hello,ActiveMQ");
//5、消息目的地
Destination destination = session.createQueue(DESTINATION);
//6、消息消费者
messageConsumer = session.createConsumer(destination);
//7、接收消息:receive方法是一个阻塞方法,它会一直等待,直到接收到消息
// receive(Long 超时毫秒数) receiveNoWait()不等待
Message receiveMessage = messageConsumer.receive();
//8、会话提交事务,如果不提交,消息不会销毁,会导致重复接收
session.commit();
if (receiveMessage instanceof TextMessage) {
String text = ((TextMessage) message).getText();
System.out.println("接收到的消息为:" + text);
}
} catch (Exception e) {
} finally {
messageConsumer.close();
session.close();
connection.close();
}
}
}
13 ActiveMQ消息确认机制
消息的成功消费通常包含三个阶段:
(1)、客户接收消息;
(2)、客户处理消息;
(3)、消息被确认;
(1)、Session.AUTO_ACKNOWLEDGE;客户(消费者)成功从receive方法返回时,或者从MessageListener.onMessage方法成功返回时,会话自动确认消息。
(2)、Session.CLIENT_ACKNOWLEDGE;客户通过显式调用消息的acknowledge方法确认消息。
(3)、Session. DUPS_OK_ACKNOWLEDGE ;不是必须确认,是一种“懒散的”消息确认,消息可能会重复发送,在第二次重新传送消息时,消息头的JMSRedelivered会被置为true标识当前消息已经传送过一次,客户端需要进行消息的重复处理控制。
(4)、 Session.SESSION_TRANSACTED;事务提交并确认。 配合事务消息的
注意:
发送者如果使用AUTO_ACKNOWLEDGE机制,接收者使用CLIENT_AACKNOWLEDGE机制,
以接收者为准。如果接收者没有手动接收,服务端的消息不会销毁。
14 ActiveMQ消息持久化
//设置发送的消息是否需要持久化
messageProducer.setDeliveryMode(DeliveryMode.NON_PERSISTENT);//不持久化
//持久化的,activemq发送消息默认都是持久化的
messageProducer.setDeliveryMode(DeliveryMode.PERSISTENT);
15 MQ技术的应用场景
1、异步处理
使用dubbo是同步的,A调用B,B马上能返回结果,调用和被调用是在同一个线程完成的,称为同步,而A调用MQ只是把请求放在消息中,等待B从消息队列中去取,然后处理将结果放在MQ中,A再过来拿结果。是一个异步的过程。
2、流量削峰
当有大量请求并发访问时,可以先返回一个成功的结果,然后使用MQ异步进行处理,比如秒杀时下单,将订单消息发送到MQ中,再慢慢消费,插入到订单表中。
3、系统解耦
16 ActiveMQ消息过滤
ActiveMQ提供了一种机制,可根据消息选择器中的标准来执行消息过滤,只接收符合过滤标准的消息;生产者可在消息中放入特有的标志,而消费者使用基于这些特定的标志来接收消息;
1、发送消息放入特殊标志:message.setStringProperty(name, value);
2、接收消息使用基于特殊标志的消息选择器:
MessageConsumer createConsumer(Destination destination, String messageSelector);
3、消息选择器是一个字符串,语法与数据库的SQL相似,相当于SQL语句where条件后面的内容;
public class QueueSender {
public static final String BROKER_URL = "tcp://localhost:61616";
public static final String DESTINATION = "myQueue";
public static void main(String[] args) throws JMSException {
//1、创建连接工厂
ConnectionFactory connectionFactory = new ActiveMQConnectionFactory(BROKER_URL);
Connection connection = null;
Session session = null;
MessageProducer producer = null;
try {
//2、创建一个连接
connection = connectionFactory.createConnection();
//3、创建一个Session,第一个参数表示是否为事务消息,第二个参数表示消息确认方式
session = connection.createSession(Boolean.FALSE, Session.AUTO_ACKNOWLEDGE);
//4、创建消息
Message message = session.createTextMessage("Hello,ActiveMQ");
//5、消息目的地
Destination destination = session.createQueue(DESTINATION);
//6、消息生产者
producer = session.createProducer(destination);
//添加消息标志
message.setIntProperty("age",20);
message.setStringProperty("name","zhangsan");
//7、发送消息
producer.send(message);
} catch (Exception e) {
} finally {
producer.close();
session.close();
connection.close();
}
}
}
public class QueueReceiver {
public static final String BROKER_URL = "tcp://localhost:61616";
public static final String DESTINATION = "myQueue";
public static void main(String[] args) throws JMSException {
//1、创建连接工厂
ConnectionFactory connectionFactory = new ActiveMQConnectionFactory(BROKER_URL);
Connection connection = null;
Session session = null;
MessageConsumer messageConsumer = null;
try {
//2、创建一个连接
connection = connectionFactory.createConnection();
//接收消息多一个步骤:把连接启动
connection.start();
//3、创建一个Session,第一个参数表示是否为事务消息,第二个参数表示消息确认方式
session = connection.createSession(Boolean.FALSE, Session.AUTO_ACKNOWLEDGE);
//4、创建消息
Message message = session.createTextMessage("Hello,ActiveMQ");
//5、消息目的地
Destination destination = session.createQueue(DESTINATION);
//定一个选择器
String selector = "age = 20 and name = 'zhangsan'";
//6、消息消费者
messageConsumer = session.createConsumer(destination,selector);
//7、接收消息:receive方法是一个阻塞方法,它会一直等待,直到接收到消息
// receive(Long 超时毫秒数) receiveNoWait()不等待
Message receiveMessage = messageConsumer.receive();
if (receiveMessage instanceof TextMessage) {
String text = ((TextMessage) message).getText();
System.out.println("接收到的消息为:" + text);
}
} catch (Exception e) {
} finally {
messageConsumer.close();
session.close();
connection.close();
}
}
}
17 ActiveMQ接收消息方式
1、同步接收
receive()方法接收消息叫同步接收;
一个线程在工作,接收到消息后,执行结束
每次只能接收一个消息
如果想不断地接收消息,那么就需要写一个while true循环
2、异步接收
使用监听器接收消息,这种接收方式叫异步接收
两个线程在工作,一个负责接收消息,一个负责处理消息
可以实现不间断地接收消息,7*24接收消息(服务没有宕机的情况下)
注意:
在同一个consumer中,我们不能同时使用这2种接收方式;
比如在使用listener的情况下,当调用receive()方法将会获得一个Exception;
public class QueueReceiver {
public static final String BROKER_URL = "tcp://localhost:61616";
public static final String DESTINATION = "myQueue";
public static void main(String[] args) throws JMSException {
//1、创建连接工厂
ConnectionFactory connectionFactory = new ActiveMQConnectionFactory(BROKER_URL);
Connection connection = null;
Session session = null;
MessageConsumer messageConsumer = null;
try {
//2、创建一个连接
connection = connectionFactory.createConnection();
//接收消息多一个步骤:把连接启动
connection.start();
//3、创建一个Session,第一个参数表示是否为事务消息,第二个参数表示消息确认方式
session = connection.createSession(Boolean.FALSE, Session.AUTO_ACKNOWLEDGE);
//4、创建消息
Message message = session.createTextMessage("Hello,ActiveMQ");
//5、消息目的地
Destination destination = session.createQueue(DESTINATION);
//6、消息消费者
messageConsumer = session.createConsumer(destination);
messageConsumer.setMessageListener(new MessageListener() {
//监听器监听到消息后,主动回调onMessage方法
@Override
public void onMessage(Message message) {
if (message instanceof TextMessage) {
String text = null;
try {
text = ((TextMessage) message).getText();
} catch (JMSException e) {
e.printStackTrace();
}
//省略进行业务逻辑的处理,插入数据库,更新状态等
System.out.println("接收到的消息为:" + text);
}
}
});
} catch (Exception e) {
}
}
}