java消息服务指的是两个应用程序之间进行异步通信的API,它为标准消息协议和消息服务提供了一组通用接口,包括创建、发送、读取消息等,等于支持JAVA应用程序开发。
在JAVAEE中,当两个应用程序使用JMS进行通信时,他们之间不是直接相连的,而是通过一个共同的消息收发服务组件关联起来已达到解耦/异步削峰的效果。
JMS provider 实现JMS接口和规范的消息中间件,也就是MQ服务器
JMS producer 消息生产者,创建和发送JMS消息的客户端应用
JMS consumer 消息消费者,接收和处理JMS消息的客户端应用
JMS message
消息头
- JMSDestination 消息发送的目的地
- JMSDeliveryMode 是持久还是非持久
- JMSExpiration 消息的过期时间,默认永不过期,消息过期时间=Destination的send方法中timetoLive值+发送时刻的GMT时间值。如果timetoLive等于0,则JMSExpiration被设为0,该消息永不过期。如果发送后,在消息过期时间之后消息还没被发送到目的地,该消息被清楚
- JMSPriority 优先级 0-9 十个级别,默认4级
- JMSMessageID 唯一识别每个消息的标识由MQ产生
消息体(封装具体的消息数据)
- TextMessage 普通字符串消 息,包含一个 String
- MapMessage Map 类型的消息, k-> String v -> Java 基本类型
- BytesMessage 二进制数组消息,包含一个byte[]
- StreamMessage Java 数据流消息, 用标准流操作来顺序的填充读取
- ObjectMessage 对象消息,包含一个可序列化的Java对象
消息属性
如果需要消息头字段以外的值,可以使用
识别/去重/重点标注等操作
queue:
设置非持久化 服务器宕机,消息不存在
设置持久化 服务器宕机,消息存在(默认)
topic:
消费者发布订阅:
一定要先运行一次消费者,等于向MQ注册,类似我订阅了这个主题
然后再运行和生产者发送信息
此时不论消费者是否在线,都能接收到消息。当消费者下次连接的时候,会把没有收过的消息都接收下来
public class JmsConsumer_topic {
public static final String ACTIVEMQ_URL = "tcp://10.1.240.97:61616";
public static final String TOPIC_NAME = "topic01";
public static void main(String[] args) throws JMSException, IOException {
System.out.println("1号消费者");
ActiveMQConnectionFactory activeMQConnectionFactory = new ActiveMQConnectionFactory(ACTIVEMQ_URL);
Connection connection = activeMQConnectionFactory.createConnection();
connection.setClientID("1hao");
connection.start();
Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
Topic topic = session.createTopic(TOPIC_NAME);
TopicSubscriber topicSubscriber = session.createDurableSubscriber(topic,"remark..");
connection.start();
Message message = topicSubscriber.receive();
while(null!=message){
TextMessage textMessage = (TextMessage) message;
System.out.println("***收到的持久化topic"+textMessage.getText());
message=topicSubscriber.receive(1000l);
}
session.close();
connection.close();
}
}
生产者
package com.atguigu.activemq.queue;
import org.apache.activemq.ActiveMQConnectionFactory;
import javax.jms.*;
public class JmsProduce_topic {
public static final String ACTIVEMQ_URL = "tcp://10.1.240.97:61616";
public static final String TOPIC_NAME= "topic01";
public static void main(String[] args) throws JMSException {
ActiveMQConnectionFactory activeMQConnectionFactory = new ActiveMQConnectionFactory(ACTIVEMQ_URL);
Connection connection = activeMQConnectionFactory.createConnection();
Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
Topic topic = session.createTopic(TOPIC_NAME);
MessageProducer producer = session.createProducer(topic);
producer.setDeliveryMode(DeliveryMode.PERSISTENT);
connection.start();//位置与非持久化的不同
for(int i=1;i<=3;i++){
TextMessage textMessage = session.createTextMessage("msg--" + i);
producer.send(textMessage);
}
producer.close();
session.close();
connection.close();
System.out.println("topic消息发送完成!");
}
}
produce提交时的事务
如果是false:只要执行 producer.send(textMessage),就进入到队列
如果是true:执行send后,在session关闭前需要执行commit,消息才真正提交到队列中
consumer提交的事务:
对于消息消费者来说,开启事务的话,可以避免消息被多次消费,以及后台和 服务器数据的不一致性。举个栗子: 如果消息消费的 createSession 设置为 ture ,但是没有 commit ,此时就会 造成非常严重的后果,那就是在后台看来消息已经被消费,但是对于服务器来说 并没有接收到消息被消费,此时就有可能被多次消费
非事务:
Session.AUTO_ACKNOWLEDGE 自动签收,默认
Session.CLIENT_ACKNOWLEDGE 手动签收
手动签收需要 textMessage.acknowledge();
事务:
Session session = connection.createSession(true,Session.AUTO_ACKNOWLEDGE); //Session session = connection.createSession(true,Session.CLIENT_ACKNOWLE DGE); // 也是自动签收 …… session.commit();
事务:
开启事务后,设置手动签收和自动签收没有多大的意义,都默认自动签 收,也就是说事务的优先级更高一些。开启事务没有commit,就会重复消费
基于队列,生产者发布消息到队列,消费者从队列接收消息,队列的存在使得消息的异步传输成为可能,和平时给朋友发送短信类似
1.如果在session关闭时有部分消息被收到但是还没有被签收,当消费者下次连到相同的队列时,这些消息还会被再次接收
2.队列可以长久的保存消息直到消费者收到消息。消费者不需要担心消息会丢失而时刻和队列保持激活的连接状态,体现了异步传输模式的优势
主题可以被认为是消息的传输中介,发布者发布消息到主题,订阅者从主题订阅消息
主题使得消息订阅者和消息发布者保持互相独立,不需要接触即可保证消息的传送
相当于一个服务器实例
broker 就是实现了用代码形式启动 ActiveMQ 将 MQ 内嵌到 Java 代码中,可 以随时启动,节省资源,提高了可靠性。 就是将 MQ 服务器作为了 Java 对象
1.导入依赖
com.fasterxml.jackson.core
jackson‐databind
2.9.5
代码实现:
public class Embebroker {
public static void main(String[] args) throws Exception {
// broker 服务
BrokerService brokerService = new BrokerService();
//把小型 activemq 服务器嵌入到 java 代码
brokerService.setUseJmx(true);
//原本的是 192.…… 是linux 上的服务器,而这里是本地windows 的小型mq 服务器
brokerService.addConnector("tcp://localhost:61616");
brokerService.start();
}
}