JMS消息服务
- JMS(Java Message Service)应用程序接口,是一个Java平台中关于面向消息中间件的API,用于在两个应用程序之间进行异步通信
- 两个应用程序之间进行异步通信,创建、发送读取消息,需要创建一个消息服务器
- JMS用来访问消息收发消息,是一种与厂商无关的API,它类似于JDBC
JMS要素
JMS两种消息传递模型
- 点对点
在点对点消息传送中,应用程序由消息队列,发送者,接收者组成。每一个消息发送给一个特殊的消息队列,该队列保存了所有发送给它的消息
- 每个消息只有一个消费者
- 发送者和接收者之间在时间上没有依赖性,也就是说当发送者发送了消息之后,不管接收者有没有在运行,它不会影响到消息被发送到队列。
- 接收者在成功接收消息之后需向队列发送确认收到通知。
- 发布/订阅
在发布/订阅模型中,发布者发布一个消息,该消息通过topic传递给所有的客户端。在这种模型中,发布者和订阅者彼此不知道对方,是匿名的且可以动态发布和订阅topic。
在发布/订阅模型中,目的地被称为主题,topic主要用于保存和传递消息,且会一直保存消息直到消息被传递给客户端。
- 每个消息有多个消费者
- 发布者和订阅者之间有时间上的依赖,针对某个主题topic的订阅者,它必须创建一个或多个订阅者之后,才能消费发布者的消息,而且为了消费消息,订阅者必须保持运行的状态
- 为了缓和这样严格的时间相关性,JMS允许订阅者创建一个可持久化的订阅,这样即使订阅者没有被激活,它也能接收到发布者的消息
ActiveMQ
PTP
1. 先开启activeMQ服务,然后登录服务页面,创建一个自己的消息队列
创建步骤:
1.创建连接Connection
2.创建会话Session
3.通过Session来创建其它的(MessageProducer、MessageConsumer、Destination、TextMessage)
4.将生产者 MessageProducer 和消费者 MessageConsumer 都会指向目标 Destination
5.生产者向目标发送TextMessage消息send()6.消费者设置监听器,监听消息。
2. 创建一个消息的生产者
public class QueueProducer
{
public void sendMessage () throws JMSException
{
ConnectionFactory connectionFactory = new ActiveMQConnectionFactory("tcp://127.0.0.1:61616");
//2.获取连接
Connection connection =
connectionFactory.createConnection();
//3.启动连接
connection.start();
//4.获取session (参数1:是否启动事务,参数2:消息确认模式)
Session session = connection.createSession(false,
Session.AUTO_ACKNOWLEDGE);
//5.创建队列对象,注意这里的名称是<u>mq</u>上创建的队列名称
Queue queue = session.createQueue("lok_que");
//6.创建消息生产者
MessageProducer producer =
session.createProducer(queue);
//7.创建消息
TextMessage textMessage =
session.createTextMessage("我是一个5秒过期的点对点消息");
//8.发送消息
//第3个参数:是否持久化 第4个参数:优先级(0~4普通 5~9加急);第5个参数:消息在ActiveMQ中间件中存放的有效期
producer.send(queue,
textMessage,DeliveryMode.PERSISTENT, 4, 1000*5);
//9.关闭资源
producer.close();
session.close();
connection.close();
}
public static void main(String[] args)
{
QueueProducer queueProducer = new QueueProducer();
try
{
queueProducer.sendMessage();
}
catch (JMSException e)
{
e.printStackTrace();
}
}
}
3. 创建一个消息消费者
public class QueueConsumer
{
public void reciveMessage() throws JMSException
{
// 1.创建连接工厂
ConnectionFactory connectionFactory = new
ActiveMQConnectionFactory("tcp://127.0.0.1:61616");
// 2.获取连接
Connection connection =
connectionFactory.createConnection();
// 3.启动连接
connection.start();
// 4.获取session (参数1:是否启动事务,参数2:消息确认模式)
Session session = connection.createSession(false,
Session.AUTO_ACKNOWLEDGE);
// 5.创建队列对象
Queue queue = session.createQueue("lok_que");
MessageConsumer consumer
=session.createConsumer(queue);
consumer.setMessageListener(new MessageListener() {
@Override
public void onMessage(Message message)
{
TextMessage textMessage =(TextMessage)
message;
try {
System.out.println("我接收到了消息"+textMessage.getText());
} catch (JMSException e) {
e.printStackTrace();
}
}
});
// 8.等待键盘输入,输入后结束
try {
System.in.read();
} catch (IOException e) {
e.printStackTrace();
}
// 9.关闭资源
consumer.close();
session.close();
connection.close();
}
public static void main(String[] args)
{
QueueConsumer consumer =new QueueConsumer();
try {
consumer.reciveMessage();
} catch (JMSException e) {
e.printStackTrace();
}
}
}
Topic
1. 先创建一个topic主题
2. 创建消息生产者
public class TopicProducer
{
public void publish() throws JMSException
{
ConnectionFactory connectionFactory =new
ActiveMQConnectionFactory("tcp://127.0.0.1:61616");
//获取连接
Connection connection
=connectionFactory.createConnection();
//启动连接
connection.start();
//获取session (参数1:是否启动事务,参数2:消息确认模式)
Session session = connection.createSession(false,
Session.AUTO_ACKNOWLEDGE);
//创建主题对象
Topic topic =session.createTopic("lok_top");
//创建消息生产者
MessageProducer producer =session.createProducer(topic);
//创建消息
TextMessage textMessage =session.createTextMessage("持久化主题消息");
//发送消息
producer.send(textMessage);
//关闭资源
producer.close();
session.close();
connection.close();
}
public static void main(String[] args)
{
TopicProducer Producer =new TopicProducer();
try {
Producer.publish();
} catch (JMSException e) {
e.printStackTrace();
}
}
}
3. 创建消息订阅者
public class TopicConsumer
{
public void recive() throws JMSException, IOException
{
// 创建连接工厂
ConnectionFactory connectionFactory = new
ActiveMQConnectionFactory("tcp://127.0.0.1:61616");
// 获取连接
Connection connection =
connectionFactory.createConnection();
// 启动连接
connection.start();
// 获取session (参数1:是否启动事务,参数2:消息确认模式)
Session session = connection.createSession(false,
Session.AUTO_ACKNOWLEDGE);
//创建主题对象
Topic topic =session.createTopic("lok_top");
//创建消息消费者,普通订阅者
MessageConsumer consumer =session.createConsumer(topic);
//创建消息监听器
consumer.setMessageListener(new MessageListener() {
@Override
public void onMessage(Message message)
{
TextMessage textMessage =(TextMessage) message;
try {
System.out.println("接收了消息"+textMessage.getText());
} catch (JMSException e) {
e.printStackTrace();
}
}
});
//等到键盘输入关闭连接
System.in.read();
//关闭资源
consumer.close();
session.close();
connection.close();
}
public static void main(String[] args)
{
TopicConsumer consumer =new TopicConsumer();
try {
consumer.recive();
} catch (JMSException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}
持久化订阅者
public class TopicConsumers
{
public void reciveMessage() throws JMSException,
IOException
{
// 1.创建连接工厂
ConnectionFactory connectionFactory = new
ActiveMQConnectionFactory("tcp://127.0.0.1:61616");
// 2.获取连接
Connection connection =
connectionFactory.createConnection();
connection.setClientID("client1"); // 持久订阅需要设置标识。
// 3.启动连接
connection.start();
// 4.获取session (参数1:是否启动事务,参数2:消息确认模式)
Session session =
connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
// 5.创建主题对象
Topic topic = session.createTopic("lok_top");
// 6.创建消息消费,持久订阅者
MessageConsumer consumer =
session.createDurableSubscriber(topic, "client1"); // 持久订阅
// 7.监听消息s
consumer.setMessageListener(new
MessageListener()
{
public void onMessage(Message message)
{
TextMessage textMessage =
(TextMessage) message;
try
{
System.out.println("接收到消息:"
+ textMessage.getText());
}
catch (JMSException e)
{
e.printStackTrace();
}
}
});
// 8.等待键盘输入,等待监听程序
System.in.read();
// 9.关闭资源
consumer.close();
session.close();
connection.close();
}
public static void main(String[] args)
{
TopicConsumers consumer = new TopicConsumers();
try
{
consumer.reciveMessage();
}
catch (JMSException e)
{
e.printStackTrace();
}
catch (IOException e)
{
e.printStackTrace();
}
}
}
topic与队列的区别
- topic是无状态的,queue数据会在MQ服务器上保存
- topic publish的每条消息不能保证都能被订阅者收到;queue能保证每条消息都能被订阅者收到
- 只有在publish消息到某一个topic时,只有在监听当前topic的订阅者那个够接收到;queue发送的消息因为会被保存,所以不会丢失