Java Message Service (JMS) 是 Java 平台上用于实现消息oriented middleware(消息中间件)的标准API。它为企业级应用中的异步通信提供了一种高效、灵活且可靠的方式,允许不同的系统组件之间通过发送和接收消息进行通信,而无需直接依赖彼此的实现细节。JMS支持两种主要的消息模型:点对点(Point-to-Point,基于队列)和发布-订阅(Publish-Subscribe,基于主题)。在本讲义中,我们将详细探讨JMS的核心概念,包括消息队列、主题、生产者与消费者模式,并通过实践实现一个异步消息通信的示例。
JMS是Java EE的一部分,主要用于在分布式系统中实现异步消息传递。通过JMS,应用程序可以以松耦合的方式交互,提高系统的响应能力和容错性。以下是JMS的一些关键概念:
JMS支持两种主要的消息目标:队列和主题。它们的主要区别在于消息的分发方式和使用场景。
1、 消息队列(Queue)
案例:在一个在线购物系统中,订单消息被发送到一个队列,订单处理系统从队列中取出订单进行处理。
2、 主题(Topic)
案例:在一个新闻平台中,新闻文章被发布到一个主题,多个移动应用订阅该主题并接收最新的新闻推送。
在JMS中,生产者和消费者是核心的角色,共同构成了异步消息传递的基本模式。
1、 生产者(Producer)
示例代码:发送消息到队列
import jakarta.jms.*;
public class MessageProducer {
public static void main(String[] args) {
ConnectionFactory connectionFactory = null;
Connection connection = null;
Session session = null;
MessageProducer producer = null;
Queue queue = null;
try {
Context context = new InitialContext();
connectionFactory = (ConnectionFactory) context.lookup("jms/ConnectionFactory");
queue = (Queue) context.lookup("jms/MyQueue");
connection = connectionFactory.createConnection();
session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
producer = session.createProducer(queue);
TextMessage message = session.createTextMessage("Hello, JMS!");
producer.send(message);
System.out.println("消息已发送。");
} catch (JMSException | NamingException e) {
e.printStackTrace();
} finally {
try {
if (producer != null) producer.close();
if (session != null) session.close();
if (connection != null) connection.close();
} catch (JMSException e) {
e.printStackTrace();
}
}
}
}
2、 消费者(Consumer)
示例代码:从队列接收消息
import jakarta.jms.*;
public class MessageConsumer {
public static void main(String[] args) {
ConnectionFactory connectionFactory = null;
Connection connection = null;
Session session = null;
Queue queue = null;
MessageConsumer consumer = null;
try {
Context context = new InitialContext();
connectionFactory = (ConnectionFactory) context.lookup("jms/ConnectionFactory");
queue = (Queue) context.lookup("jms/MyQueue");
connection = connectionFactory.createConnection();
session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
consumer = session.createConsumer(queue);
// 异步接收消息
consumer.setMessageListener(new MessageListener() {
@Override
public void onMessage(Message message) {
if (message instanceof TextMessage) {
try {
String text = ((TextMessage) message).getText();
System.out.println("接收到消息:" + text);
} catch (JMSException e) {
e.printStackTrace();
}
}
}
});
System.out.println("等待接收消息...");
connection.start();
} catch (JMSException | NamingException e) {
e.printStackTrace();
} finally {
try {
if (consumer != null) consumer.close();
if (session != null) session.close();
if (connection != null) connection.close();
} catch (JMSException e) {
e.printStackTrace();
}
}
}
}
在本节中,我们将通过一个实践示例,展示如何使用JMS实现异步消息通信。这个示例包括以下步骤:
1、 环境设置
pom.xml
中添加JMS和ActiveMQ的依赖。示例pom.xml依赖:
<dependencies>
<dependency>
<groupId>jakarta.jmsgroupId>
<artifactId>jakarta.jms-apiartifactId>
<version>3.1.0version>
dependency>
<dependency>
<groupId>org.apache.activemqgroupId>
<artifactId>activemq-brokerartifactId>
<version>5.17.3version>
dependency>
<dependency>
<groupId>org.apache.activemqgroupId>
<artifactId>activemq-clientartifactId>
<version>5.17.3version>
dependency>
dependencies>
2、 实现消息生产者
编写一个Java类,使用JMS API向ActiveMQ的队列发送消息。
import jakarta.jms.*;
import javax.naming.Context;
import javax.naming.InitialContext;
import java.util.Properties;
public class MessageProducer {
public static void main(String[] args) {
// 配置ActiveMQ连接工厂
Properties properties = new Properties();
properties.setProperty(Context.INITIAL_CONTEXT_FACTORY,
"org.apache.activemq.jndi.ActiveMQInitialContextFactory");
properties.setProperty(Context.PROVIDER_URL, "tcp://localhost:61616");
try {
// 获取JNDI上下文
Context context = new InitialContext(properties);
// 查找连接工厂和队列
ConnectionFactory connectionFactory =
(ConnectionFactory) context.lookup("ConnectionFactory");
Queue queue = (Queue) context.lookup("MyQueue");
// 创建连接和会话
Connection connection = connectionFactory.createConnection();
Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
// 创建消息生产者
MessageProducer producer = session.createProducer(queue);
// 创建和发送消息
TextMessage message = session.createTextMessage("您好,JMS!");
producer.send(message);
System.out.println("消息已发送。");
// 关闭资源
producer.close();
session.close();
connection.close();
} catch (JMSException | javax.naming.NamingException e) {
e.printStackTrace();
}
}
}
3、 实现消息消费者
编写一个Java类,从ActiveMQ的队列中异步接收和处理消息。
import jakarta.jms.*;
import javax.naming.Context;
import javax.naming.InitialContext;
import java.util.Properties;
public class MessageConsumer {
public static void main(String[] args) {
// 配置ActiveMQ连接工厂
Properties properties = new Properties();
properties.setProperty(Context.INITIAL_CONTEXT_FACTORY,
"org.apache.activemq.jndi.ActiveMQInitialContextFactory");
properties.setProperty(Context.PROVIDER_URL, "tcp://localhost:61616");
try {
// 获取JNDI上下文
Context context = new InitialContext(properties);
// 查找连接工厂和队列
ConnectionFactory connectionFactory =
(ConnectionFactory) context.lookup("ConnectionFactory");
Queue queue = (Queue) context.lookup("MyQueue");
// 创建连接和会话
Connection connection = connectionFactory.createConnection();
Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
// 创建消息消费者并设置监听器
MessageConsumer consumer = session.createConsumer(queue);
consumer.setMessageListener(new MessageListener() {
@Override
public void onMessage(Message message) {
if (message instanceof TextMessage) {
try {
String text = ((TextMessage) message).getText();
System.out.println("接收到消息:" + text);
} catch (JMSException e) {
e.printStackTrace();
}
}
}
});
// 启动连接以接收消息
connection.start();
System.out.println("等待接收消息...");
} catch (JMSException | javax.naming.NamingException e) {
e.printStackTrace();
}
}
}
4、 运行和测试
启动ActiveMQ:
打开终端,运行ActiveMQ的启动脚本,例如:
activemq start
创建队列:
admin
/admin
。MyQueue
作为队列名称,创建新的队列。运行消息生产者:
执行MessageProducer
类,观察控制台输出,应该显示“消息已发送。”
运行消息消费者:
在另一个终端窗口中执行MessageConsumer
类,观察控制台输出,应该显示“接收到消息:您好,JMS!”。同时,ActiveMQ Web Console中的队列也应该显示消息已被消费。
注意事项:
61616
和8161
处于监听状态。Context.INITIAL_CONTEXT_FACTORY
和Context.PROVIDER_URL
的设置。finally
块中确保所有JMS资源被关闭,避免资源泄漏。最佳实践:
通过本讲义,我们详细探讨了Java Message Service (JMS)的核心概念,包括消息队列、主题、生产者与消费者模式,并通过一个实践示例实现了异步消息通信。JMS为企业级应用提供了一种高效、可靠的通信方式,能够有效分离系统的不同组件,提升系统的可扩展性和响应能力。掌握JMS的使用和配置,对于构建高效、可靠的分布式系统至关重要。
关键点总结: