一、JMS 介绍
消息传递是软件组件或应用程序之间的通信的方法。消息系统是一种对等网络设施:一个消息客户端可以发送邮件到,并接收来自任何其他客户端的消息。 每个客户端连接到一个消息传递代理,它提供了创建,发送,接收和读取消息的设施。
消息使松散耦合的分布式通信。 一个组件发送一个消息到目的地,并且接收方可以检索来自目的地的消息。 然而,发送者和接收者不必是可在同一时间,以进行通信。事实上,发送者并不需要知道接收任何事情; 也不接收器需要知道发送什么。 发送器和接收器只需要知道消息格式和目的地要使用的。 在这方面,消息不同于紧耦合的技术,如远程方法调用(RMI),这需要一个应用程序知道远程应用程序的方法。消息也不同于电子邮件(email),这是人们之间或软件应用程序和人之间的通信的方法。 消息是用于软件应用程序或软件组件之间的通信。Java消息服务是一个Java API,允许应用程序创建,发送,接收和读取消息。 由Sun和几个合作伙伴公司设计,JMS API定义了一组通用的接口和相关的语义,允许用Java编程语言程序与其他消息实现者之间实现通信。Java消息服务(Java Message Service,JMS)应用程序接口是一个Java平台中关于面向消息中间件(MOM)的API,用于在两个应用程序之间,或分布式系统中发送消息,进行异步通信。Java消息服务是一个与具体平台无关的API,绝大多数MOM提供商都对JMS提供支持。Java消息服务的规范包括两种消息模式,点对点和发布者/订阅者。许多提供商支持这一通用框架因此,程序员可以在他们的分布式软件中实现面向消息的操作,这些操作将具有不同面向消息中间件产品的可移植性。Java消息服务支持同步和异步的消息处理,在某些场景下,异步消息是必要的;在其他场景下,异步消息比同步消息操作更加便利。Java消息服务支持面向事件的方法接收消息,事件驱动的程序设计现在被广泛认为是一种富有成效的程序设计范例,程序员们都相当熟悉。在应用系统开发时,Java消息服务可以推迟选择面对消息中间件产品,也可以在不同的面对消息中间件切换。
实现方式
Queue仅允许一个消息传送给一个客户(一对一):Java消息服务JMS的接收者和发送者之间不存在时间上的依赖关系。不论发送者发送消息时接收者是否在运行,接收者都可以提取信息。接收者对于成功处理的消息给出回执。
Topics可以有多个客户端(一对多,多对多):向某个话题订阅的客户程序只能收到那些在它订阅之后发布的消息。为了接收到消息,订阅者必须保持活动状态。因此,发布者和订阅者之间存在时间上的依赖关系。
点对点消息模式通过一个消息队列(Queue)实现,消息的生产者向队列写入消息,消息的订阅者从队列提取消息。
发布-订阅消息模式通过一个话题(Topic)节点构成的层次结构实现,消息的生产者向这个层次结构发布消息,消息的订阅者向这个结构订阅消息。消息驱动的Bean只有一个Bean类。从某些方面看,JMS消息驱动的Bean类似于无状态会话Bean:消息驱动的Bean不为特定的客户保留数据或对话状态。
二、JMS实现
依赖的jar包,pom配置:
<dependency>
<groupId>javax.jms</groupId>
<artifactId>jms</artifactId>
<version>1.1</version>
</dependency>
<dependency>
<groupId>org.apache.activemq</groupId>
<artifactId>activemq-core</artifactId>
<version>5.4.2</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jms</artifactId>
<version>3.0.4.RELEASE</version>
</dependency>
<dependency>
<groupId>org.apache.activemq</groupId>
<artifactId>activemq-pool</artifactId>
<version>5.4.2</version>
</dependency>
直接代码如下:
发送消息:
import org.apache.activemq.ActiveMQConnection;
import org.apache.activemq.ActiveMQConnectionFactory;
import javax.jms.*;
/**
* Created by ldc
*/
public class Sender {
private static final int SEND_NUMBER = 5;
public static void main(String[] args) {
// ConnectionFactory :连接工厂,JMS 用它创建连接
ConnectionFactory connectionFactory;
// Connection :JMS 客户端到JMS Provider 的连接
Connection connection = null;
// Session: 一个发送或接收消息的线程
Session session;
// Destination :消息的目的地;消息发送给谁.
Destination destination;
// MessageProducer:消息发送者
MessageProducer producer;
// TextMessage message;
// 构造ConnectionFactory实例对象,此处采用ActiveMq的实现jar
connectionFactory = new ActiveMQConnectionFactory(
ActiveMQConnection.DEFAULT_USER,
ActiveMQConnection.DEFAULT_PASSWORD,
"tcp://localhost:61616");
try {
// 构造从工厂得到连接对象
connection = connectionFactory.createConnection();
// 启动
connection.start();
// 获取操作连接
session = connection.createSession(Boolean.TRUE,
Session.AUTO_ACKNOWLEDGE);
// 获取session注意参数值xingbo.xu-queue是一个服务器的queue,须在在ActiveMq的console配置
destination = session.createQueue("ActiveQueue");
// 得到消息生成者【发送者】
producer = session.createProducer(destination);
// 设置不持久化,此处学习,实际根据项目决定
producer.setDeliveryMode(DeliveryMode.NON_PERSISTENT);
// 构造消息,此处写死,项目就是参数,或者方法获取
sendMessage(session, producer);
session.commit();
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
if (null != connection)
connection.close();
} catch (Throwable ignore) {
}
}
}
public static void sendMessage(Session session, MessageProducer producer)
throws Exception {
for (int i = 1; i <= SEND_NUMBER; i++) {
TextMessage message = session
.createTextMessage("ActiveMq 发送的消息" + i);
// 发送消息到目的地方
System.out.println("发送消息:" + "ActiveMq 发送的消息" + i);
producer.send(message);
}
}
}
接受消息(同步):
import org.apache.activemq.ActiveMQConnection;
import org.apache.activemq.ActiveMQConnectionFactory;
import javax.jms.*;
/**
* Created by ldc
*/
public class Receiver {
public static void main(String[] args) {
// ConnectionFactory :连接工厂,JMS 用它创建连接
ConnectionFactory connectionFactory;
// Connection :JMS 客户端到JMS Provider 的连接
Connection connection = null;
// Session: 一个发送或接收消息的线程
Session session;
// Destination :消息的目的地;消息发送给谁.
Destination destination;
// 消费者,消息接收者
MessageConsumer consumer;
connectionFactory = new ActiveMQConnectionFactory(
ActiveMQConnection.DEFAULT_USER,
ActiveMQConnection.DEFAULT_PASSWORD,
"tcp://localhost:61616");
try {
// 构造从工厂得到连接对象
connection = connectionFactory.createConnection();
// 启动
connection.start();
// 获取操作连接
session = connection.createSession(Boolean.FALSE,
Session.AUTO_ACKNOWLEDGE);
// 获取session注意参数值xingbo.xu-queue是一个服务器的queue,须在在ActiveMq的console配置
destination = session.createQueue("ActiveQueue");
consumer = session.createConsumer(destination);
while (true) {
//设置接收者接收消息的时间,为了便于测试,这里定为100s
TextMessage message = (TextMessage) consumer.receive(100000);
if (null != message) {
System.out.println("收到消息" + message.getText());
} else {
break;
}
}
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
if (null != connection)
connection.close();
} catch (Throwable ignore) {
}
}
}
}
接受消息(监听):
import org.apache.activemq.ActiveMQConnection;
import org.apache.activemq.ActiveMQConnectionFactory;
import javax.jms.*;
import javax.jms.Message;
/**
* Created by ldc.
*/
public class ReceiveMessage implements MessageListener {
private String user = ActiveMQConnection.DEFAULT_USER;
private String password = ActiveMQConnection.DEFAULT_PASSWORD;
private javax.jms.Connection connection = null;
private Session session = null;
private MessageConsumer consumer = null;
public void onMessage(Message message) {
try {
if (message instanceof TextMessage) {
TextMessage txtMsg = (TextMessage) message;
System.out.println("Received: " + txtMsg.getText());
} else {
System.out.println("Received: " + message);
}
} catch (JMSException e) {
//ldc
}
}
public void initMessage() throws JMSException {
// 连接工厂是用户创建连接的对象,这里使用的是ActiveMQ的ActiveMQConnectionFactory根据url,username和password创建连接工厂。
String url = "tcp://localhost:61616";
ActiveMQConnectionFactory connectionFactory = new ActiveMQConnectionFactory(user, password, url);
// 连接工厂创建一个jms connection
connection = connectionFactory.createConnection();
// 是生产和消费的一个单线程上下文。会话用于创建消息的生产者,消费者和消息。会话提供了一个事务性的上下文。
session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE); // 不支持事务
// 目的地是客户用来指定他生产消息的目标还有他消费消息的来源的对象,两种消息传递方式:点对点和发布/订阅
String subject = "ActiveQueue";
Destination destination = session.createQueue(subject);
// 会话创建消息的生产者将消息发送到目的地
consumer = session.createConsumer(destination);
}
// 消费消息
public void consumeMessage() throws JMSException, Exception {
initMessage();
connection.start();
// 开始监听
consumer.setMessageListener(this);
}
// 关闭连接
public void close() {
try {
if (consumer != null) {
consumer.close();
}
if (session != null) {
session.close();
}
if (connection != null) {
connection.close();
}
} catch (JMSException e) {
e.printStackTrace();
}
}
public static void main(String[] args) {
ReceiveMessage receiveMessage = new ReceiveMessage();
try {
receiveMessage.consumeMessage();
} catch (Exception e) {
receiveMessage.close();
}
}
}
运行完成后可通过本地的ActiveMQ具体查看具体参考 ActiveMQ 的使用