java消息服务(JMS)可以提供不同系统之间的消息传递,和rpc有相似之处。
不过rpc一般是进行阻塞调用,导致系统之间高度耦合,其中一个系统的失效会对其他系统造成立竿见影的弱化影响。如果系统间有很多垂直的模块集成在一起,那么模块间相互调用不仅数量众多,而且方向也是错综复杂的。
而消息传送系统规定应用程序之间采用异步通信方式,不需要立即从另一应用程序得到响应,不会出现阻塞现象。一旦消息被发送到消息服务器,接下来的事就不需要考虑了。JMS提供了一个松散耦合的环境,系统组件的局部故障不会妨碍系统的整体可用性。
JMS可以分为发布/订阅模型和点对点队列模型。
JMS API可以分为公共API、点对点API、发布/订阅API三部分。
公共API接口主要有7个:
javax.jms.ConnectionFactory
javax.jms.Destination
javax.jms.Connection
javax.jms.Session
javax.jms.Message
javax.jms.MessageProducer
javax.jms.MessageConsumer
点对点API:
javax.jms.QueueConnectionFactory
javax.jms.Queue
javax.jms.QueueConnection
javax.jms.QueueSession
javax.jms.Message
javax.jms.QueueSender
javax.jms.QueueReceiver
发布/订阅API
javax.jms.TopicConnectionFactory
javax.jms.Topic
javax.jms.TopicConnection
javax.jms.TopicSession
javax.jms.Message
javax.jms.TopicPublisher
javax.jms.TopicSubscriber
JMS消息有持久化/非持久化消息和事务性/非事务性消息之分。我自己做了测试。
代码是以ActiveMQ做的例子
package shjh.jms;
import org.apache.activemq.ActiveMQConnectionFactory;
import javax.jms.*;
public class QueueProducer {
private QueueConnectionFactory connectionFactory;
private QueueConnection connection;
private QueueSession session;
private Queue queue1;
QueueProducer() throws JMSException {
//创建工厂
connectionFactory = new ActiveMQConnectionFactory("tcp://localhost:61616");
//创建连接
connection = connectionFactory.createQueueConnection();
//创建会话,第一个参数true代表事务性会话
session = connection.createQueueSession(true, Session.AUTO_ACKNOWLEDGE);
//输出会话是否是事务性的
System.out.println(session.getTransacted());
queue1 = session.createQueue("queue1");
connection.start();
}
public void sendMessage(){
try {
MapMessage mapMessage = session.createMapMessage();
mapMessage.setString("name", "shjh");
mapMessage.setString("age", "21");
//创建消息发送者,目标动态队列queue1
QueueSender sender = session.createSender(queue1);
//设置为非持久化消息(经测试,默认为持久化消息)
sender.setDeliveryMode(DeliveryMode.NON_PERSISTENT);
sender.send(mapMessage);
//因为是事务性消息,需要commit
session.commit();
} catch (JMSException e) {
try {
//事务性消息,异常rollback
session.rollback();
} catch (JMSException e1) {
e1.printStackTrace();
}
e.printStackTrace();
}
}
public void exit(){
try {
//结束时关闭连接
connection.close();
} catch (JMSException e) {
e.printStackTrace();
}
}
public static void main(String[] args){
QueueProducer producer = null;
try {
producer = new QueueProducer();
producer.sendMessage();
} catch (JMSException e) {
e.printStackTrace();
}finally {
producer.exit();
}
}
}
首先启动activemq。
测试情况
1、发送一条非持久化消息。
队列queue1有一条消息,消息详细信息如下
可以看出为Non Persistent ,非持久化消息,保存在内存中,这时候如果消息未被消费者处理,而JMS提供者出现故障(手动模拟关闭),消息将消失。如下图
我重启Activemq之后消息为0.
2、发送持久化消息测试,
sender.setDeliveryMode(DeliveryMode.PERSISTENT);
之后手动重启activemq,消息仍然在queue1队列中,并且状态为Persistent ,不再截图了。
3、事务性消息测试,
session = connection.createQueueSession(true, Session.AUTO_ACKNOWLEDGE);
第一个参数设置为true之后,开启事务,下面发送消息之后一定要手动调用session.commit();,异常session.rollback();否则jms服务器上无法收到消息,不截图了,有兴趣自己测试看看。