JMS 规范以及消息特性(一)

JMS规范是什么

它是JavaEE体系中的一项Message Service

常用消息中间件比较

JMS组成和特点

JMS provider

实现jms接口的消息中间件

JMS Producer 、JMS Constomer


JMS Message 消息头

1)jms destination 消息目的地 队列或者主题
2)jms deviverymode 持久化方式
3)jms expiration 消息过期时间 
4)jms 优先级 1到4是普通消息  5-9是加急消息
5)消息id  唯一识别每个消息的标识,是有MQ自己生成
消息头之destination

在这里插入图片描述
当然,也可以通过消息进行设置
在这里插入图片描述

四种重载:目的地,消息,优先级,存活时间,是否持久化
消息的目的地:队列 和 主题

持久性
在这里插入图片描述
消息的过期时间 默认是永不过期的

消息体

发送的消息类型有哪些:
StringMessage MapMessage ByteMessage StringMessage ObjectMessage 五中类型

要求:发送的消息体和接受的消息体要求类型一致。

在这里插入图片描述
要求:发送的消息体和接受的消息体要求类型一致。
在这里插入图片描述

自定义的消息属性

自定义的消息属性能有什么还用呢 ?
去重、识别、重点标注等	

TextMessage textMessage = session.createTextMessage("myTopic……"+ i );
messageProducer.send(textMessage);
textMessage.setStringProperty("自定义消息的key", "自定义消息的value");

如何保证消息的可靠性???

消息的可靠性可以从以下四个方面来回答:
1)消息的持久性
2)消息的事务特性
3)消息的签收机制
4)消息持久化

(队列)消息的持久性

在这里插入图片描述
验证1:
设置消息为非持久性,然后生产消息,(服务器不关闭),再去消费消息
在这里插入图片描述
消息被正常消费
在这里插入图片描述
验证2:
设置消息为非持久性,然后生产消息,(服务器关闭),再去消费消息
生成出的消息
在这里插入图片描述
服务器关闭之后,再去消费消息
在这里插入图片描述
消息丢失,不能被消费。
刚刚生成的消息被丢失了
在这里插入图片描述
验证3:设置消息为持久性,然后生成消息。这个是刚刚生成的消息。
在这里插入图片描述
关闭消息服务器,再次重新启动消息,消息依旧存在
在这里插入图片描述
去消费消息。消息成功被消费
在这里插入图片描述
在这里插入图片描述

(topic)消息的持久性

对于topic消息,持久性没有多大意义,因为在topic模式中,需要先启动消费者,然后再启动生产者,如果设置了消息持久性,但是,还没有启动动消费者,则这些消息就会被丢失,不能被消费者消费

设置持久化的topic生成者

package com.ttzz.activemq;

import javax.jms.Connection;
import javax.jms.DeliveryMode;
import javax.jms.JMSException;
import javax.jms.MessageProducer;
import javax.jms.Session;
import javax.jms.TextMessage;
import javax.jms.Topic;

import org.apache.activemq.ActiveMQConnectionFactory;

public class ActiveMQProduceByTopic {
    
    
	public static String url = "tcp://localhost:61616";
	public static String topicName = "myTopic";
	
	public static void main(String[] args) throws JMSException {
    
    
		//1.获取工厂
		ActiveMQConnectionFactory activeMQConnectionFactory = new ActiveMQConnectionFactory(url);
		//2. 创建连接
		Connection connection = activeMQConnectionFactory.createConnection();
		
		//3.创建会话
		// 第一个参数 是否开启开启事务
		// 第二个参数 是签收模式
		Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
		//4. 创建目的地 Topic 
		Topic topic =session.createTopic(topicName);
		//5. 创建生产者
		MessageProducer messageProducer = session.createProducer(topic);
		
		messageProducer.setDeliveryMode(DeliveryMode.PERSISTENT);
		connection.start();
		//6. 发送消息
		for (int i = 0; i < 4; i++) {
    
    
			TextMessage textMessage = session.createTextMessage("myTopic……"+ i );
			textMessage.setStringProperty("自定义消息的key", "自定义消息的value");
			messageProducer.send(textMessage);
		}
		//关闭资源
		messageProducer.close();
		session.close();
		connection.close();
		System.out.println("OOKK");
	}
}

topic 消费者

package com.ttzz.activemq;

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 javax.jms.Topic;
import javax.jms.TopicSubscriber;

import org.apache.activemq.ActiveMQConnectionFactory;

public class ActiveMQConsumerByTopic {
    
    
	public static String url = "tcp://localhost:61616";
	public static String topicName = "myTopic";

	public static void main(String[] args) throws JMSException, IOException {
    
    
		// 1.获取工厂
		ActiveMQConnectionFactory activeMQConnectionFactory = new ActiveMQConnectionFactory(url);
		// 2. 创建连接
		Connection connection = activeMQConnectionFactory.createConnection();
		
		connection.setClientID("消费者1");
		System.out.println("topic消费者1");
		
		// 3.创建会话
		// 第一个参数 是否开启开启事务
		// 第二个参数 是签收模式
		Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
		// 4. 创建目的地Topic
		Topic topic = session.createTopic(topicName);
		// 5. 创建消费者
		TopicSubscriber topicSubscriber = session.createDurableSubscriber(topic, "remark..."); // 创建持久化的订阅

		connection.start();

		Message message = topicSubscriber.receive();
		while (message != null) {
    
    
			TextMessage textMessage = (TextMessage) message;
			System.out.println(textMessage.getText());
			message = topicSubscriber.receive();
		}

		session.close();
		connection.close();
		System.out.println("OOKK2");
	}
}

验证1:启动一个消费者
在这里插入图片描述
在这里插入图片描述
Active Durable Topic Subscribers :处于激活状态的持久化的topic消费者
Offline Durable Topic Subscribers:处于离线状态的持久化的topic消费者
启动持久化的topic生成者:
topic消费者消费消息
在这里插入图片描述
消息服务器
在这里插入图片描述
在这里插入图片描述
验证2:将消费者1 关闭,启动消费者2
在这里插入图片描述
消费者1处于离线状态,启动生成者消费
在这里插入图片描述
消费者2能够正常消费消息
在这里插入图片描述
再次启动消费者1,消费者1也能正常消费消息
在这里插入图片描述
在这里插入图片描述

消息的事务特性

事务主要是针对生产者,签收主要针对消费者

	//3.创建会话
	// 第一个参数 是否开启开启事务
	// 第二个参数 是签收模式
	Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);

验证1:
事务设置为 false,执行发送消息,消息自动到服务器
在这里插入图片描述
在这里插入图片描述
因为设置了消息的持久性,关闭服务器,再次重启启动,该消息依旧存在

扫描二维码关注公众号,回复: 13053336 查看本文章

验证2:
事务设置为 true,执行发送消息,
在这里插入图片描述

看看服务器有没有收到消息。服务器中没有收到刚刚发送的消息。因为没有做消息的提交操作
在这里插入图片描述
提交事务
在这里插入图片描述
消息入队
在这里插入图片描述
事务对于多个消息同时发送,能够保证原子性
session.rollback();

为了验证的需要,需要重启的时候,删除持久化的消息

操作:在配置文件activemq.xml的broker字段添加deleteAllMessagesOnStartup=“true”
在这里插入图片描述
在这里插入图片描述
可以看到持久化的消息被删除,

生成者开启事务,将消息发送到消息服务器
在这里插入图片描述
看到消息
在这里插入图片描述
消费者消费掉消息
在这里插入图片描述
再次启动一个消费者,发现消息已经被消费,说明消息不能被重新消费
在这里插入图片描述
验证2:设置消费者开启事务,但是,没有提交事务【消息被重复消费】。第一次,消费者1正常消费消息,
在这里插入图片描述
但是在服务器看到:消息没有被消费
在这里插入图片描述
再次启动另一个消费者,发现消息可以被多次消费
在这里插入图片描述

一个有趣的现象

生成者以事务的方式将生成者发送到服务器
消费者开启事务进行消费,但是,没有提交事务。保证控制到不灭。再次启动2号消费者,发现不能重复消费???
在这里插入图片描述
在这里插入图片描述
如果(去掉: System.in.read();)设置消费者4秒之后,没有消息,自动关闭。则启动2号消费者,可以重复消费。
原因呢???哈哈哈哈

猜你喜欢

转载自blog.csdn.net/weixin_39472101/article/details/114993631