JMS学习心得(一)
2009-07-22 15:17
246 查看
学习中的一些心得记录
p2p方式:
概念:queue,QueueSender,QueueReceiver,队列,消息发送者,消息接收者三个角色。发送者向队列中加入消息,接收者从队列取出消息,队列中的消息接收一条少一条,如果有多个接收者连接到队列,一条消息只能被一个接收者取走。
一、
消息发送方式默认不设置的时候是 DeliveryMode.PERSISTENT
方式,也就是持久化方式。该常量值为2。这种方式消息不会丢失,会保存在服务器上。就是说消息发送后,即使你关闭jms服务器(比如用activeMQ,
关闭服务器程序),然后服务重新启动后,这条消息仍然是存在的,而其他使用NON_PERSISTENT方式的消息就丢失了。我想大多数情况下啊我们需要
的是PERSISTENT方式吧!
DeliveryMode.NON_PERSISTENT 常量值为1
DeliveryMode.PERSISTENT 常量值为2
int a = msgp0.getDeliveryMode();
//msgp0.setDeliveryMode(DeliveryMode.PERSISTENT);
二、消息的消费者接收消息可以采用两种方式:
1、consumer.receive() 或 consumer.receive(int timeout);
2、注册一个MessageListener。
采用第一种方式,即同步方式,遇到receive方法就会阻塞,消息的接收者会一直等待下去,直到有消息到达,或者超时。该方式调用一次方法只接收一条消息。
采用第二种方式,即异步方式,程序会一直监听,只要有消息就会响应onMessage方法,当执行
conn.close()方法时会结束监听器。
MessageConsumer comsumer
=
session.createConsumer(queue);
comsumer.setMessageListener(
new
MessageListener(){
@Override
public
void
onMessage(Message m) {
TextMessage textMsg
=
(TextMessage) m;
try
{
System.out.println(textMsg.getText());
}
catch
(JMSException e) {
e.printStackTrace();
}
}
});
测试发现
conn.close()
方法对这两种方式有些不同,对于监听器方式,只要close方法执行,监听就会终止,估计监听是以后台线程方式执行的。而对于recive接收方式,只要
receive方法只要调用一次,就必须等到有消息到达才会执行下面的语句,是阻塞的方式,即使后面的conn.close()不会执行到。
参考:http://www.cnblogs.com/iloveu/archive/2009/06/10/1500714.html
pub/sub方式
:
概念:topic,publisher,subscriber,主题,发布者,订阅者三个角色。主题和订阅者是一对多关系,一个主题可以被多个订阅者订阅。当发布者向某个主题发送一条消息时,所有的订阅者都会收到。
如何理解订阅的概念呢,个人理解,分两种情况:
一、
创建一个订阅者时使用session.createDurableSubscriber(topic, clientId
)方法创建为持久型订阅者时,该topic和clientId的订阅关系将被保存在服务器上,即产生了订阅关系。这样clientId这个id的订阅者将
在离线的时候,也不会丢失消息。这个订阅关系也可以理解为被持久化在jms服务器上了,使用jmx的监视控制台(我使用的activeMq),可以看到有
一个Subscription的节点,下面有你订阅主题时给定的客户端名字。可以使用unsubscribe
方法
取消订阅关系。
二、
创建一个非持久化方式的订阅者时,只有在客户端订阅者连接到jms服务器时,订阅关系成立,订阅者离线时,订阅关系即取消,不会保存在服务器上,这也是非
持久化方式订阅者不能离线接收消息的原因吧。默认为广播方式,在没有订阅者连接到服务器时,发送的消息将丢失,不会保存在服务器。
对jms规范的理解:
jms
规范是sun提出的java的消息服务统一的api接口规范,规范、标准的好处就不用说了,java能走到今天,规范标准的制定可以说有很大的功劳吧。所
有提供java消息服务的软件提供者都必须针对这个接口实现。我们编写jms程序时,基本可以做到只针对接口编程,不用考虑是那个厂家实现,这是我们的代
码有了很大的灵活行,不绑定某个具体厂商。只要你的代码写的够好,完全可以不修改代码就直接部署到不同厂商的jms服务器上。
举个例子:编写一个基于ActiveMQ的jms程序时有这样的代码:
ActiveMQConnectionFactory factory = new
ActiveMQConnectionFactory("vm://localhost"
);
...
Queue queue = new
ActiveMQQueue("testQueue"
);
等,这样就在代码里绑死了ActiveMQ的api。要做到厂商无关性,应该使用jndi来取得工厂对象以及队列资源。
比如:
ConnectionFactory cf = (ConnectionFactory) ctx.lookup("connectionFactory");
...
Destination dest = (Queue) ctx.lookup("MyQueue");
注意接口也尽量使用jms的大的接口。当然这里需要提供jndi服务支持,ActiveMQ本身提供jndi服务,只要在classpath中有一个jndi.properties文件,在配置文件中对资源做一些配置就可以了
比如:
java.naming.factory.initial = org.apache.activemq.jndi.ActiveMQInitialContextFactory
connectionFactoryNames = connectionFactory, queueConnectionFactory, topicConnectionFactry
queue.MyQueue = zmQueue
topic.MyTopic = zmTopic
等。
对jms规范1.1的一些理解:
JMS 1.0.2 定义了两种类型的消息传递域(它们是相互独立的),即点对点和发布/订阅。JMS 的最新版本,即版本 1.1,JMS 统一了这两个域。如下图:有了 JMS 1.1,客户机就不再必须专门针对这个或那个域进行实现了。
参考:http://www.ibm.com/developerworks/cn/java/j-jms11/index.html
就是说,只使用JMS公共域的接口就可以完成jms程序编写。所以推荐尽量使用大的接口,增加代码的灵活性。
比如,写pub/sub方式的消息程序也可以这样:
Context ctx = new InitialContext();
ConnectionFactory factory = (ConnectionFactory) ctx
.lookup("connectionFactory");
Connection connection = factory.createConnection();
connection.start();
// 创建一个Topic
Destination topic = (Destination) ctx.lookup("MyTopic");
Session session = connection.createSession(false,
Session.AUTO_ACKNOWLEDGE);
MessageConsumer comsumer3 = session.createConsumer(topic);
Message msg = comsumer3.receive();
p2p方式:
概念:queue,QueueSender,QueueReceiver,队列,消息发送者,消息接收者三个角色。发送者向队列中加入消息,接收者从队列取出消息,队列中的消息接收一条少一条,如果有多个接收者连接到队列,一条消息只能被一个接收者取走。
一、
消息发送方式默认不设置的时候是 DeliveryMode.PERSISTENT
方式,也就是持久化方式。该常量值为2。这种方式消息不会丢失,会保存在服务器上。就是说消息发送后,即使你关闭jms服务器(比如用activeMQ,
关闭服务器程序),然后服务重新启动后,这条消息仍然是存在的,而其他使用NON_PERSISTENT方式的消息就丢失了。我想大多数情况下啊我们需要
的是PERSISTENT方式吧!
DeliveryMode.NON_PERSISTENT 常量值为1
DeliveryMode.PERSISTENT 常量值为2
int a = msgp0.getDeliveryMode();
//msgp0.setDeliveryMode(DeliveryMode.PERSISTENT);
二、消息的消费者接收消息可以采用两种方式:
1、consumer.receive() 或 consumer.receive(int timeout);
2、注册一个MessageListener。
采用第一种方式,即同步方式,遇到receive方法就会阻塞,消息的接收者会一直等待下去,直到有消息到达,或者超时。该方式调用一次方法只接收一条消息。
采用第二种方式,即异步方式,程序会一直监听,只要有消息就会响应onMessage方法,当执行
conn.close()方法时会结束监听器。
MessageConsumer comsumer
=
session.createConsumer(queue);
comsumer.setMessageListener(
new
MessageListener(){
@Override
public
void
onMessage(Message m) {
TextMessage textMsg
=
(TextMessage) m;
try
{
System.out.println(textMsg.getText());
}
catch
(JMSException e) {
e.printStackTrace();
}
}
});
测试发现
conn.close()
方法对这两种方式有些不同,对于监听器方式,只要close方法执行,监听就会终止,估计监听是以后台线程方式执行的。而对于recive接收方式,只要
receive方法只要调用一次,就必须等到有消息到达才会执行下面的语句,是阻塞的方式,即使后面的conn.close()不会执行到。
参考:http://www.cnblogs.com/iloveu/archive/2009/06/10/1500714.html
pub/sub方式
:
概念:topic,publisher,subscriber,主题,发布者,订阅者三个角色。主题和订阅者是一对多关系,一个主题可以被多个订阅者订阅。当发布者向某个主题发送一条消息时,所有的订阅者都会收到。
如何理解订阅的概念呢,个人理解,分两种情况:
一、
创建一个订阅者时使用session.createDurableSubscriber(topic, clientId
)方法创建为持久型订阅者时,该topic和clientId的订阅关系将被保存在服务器上,即产生了订阅关系。这样clientId这个id的订阅者将
在离线的时候,也不会丢失消息。这个订阅关系也可以理解为被持久化在jms服务器上了,使用jmx的监视控制台(我使用的activeMq),可以看到有
一个Subscription的节点,下面有你订阅主题时给定的客户端名字。可以使用unsubscribe
方法
取消订阅关系。
二、
创建一个非持久化方式的订阅者时,只有在客户端订阅者连接到jms服务器时,订阅关系成立,订阅者离线时,订阅关系即取消,不会保存在服务器上,这也是非
持久化方式订阅者不能离线接收消息的原因吧。默认为广播方式,在没有订阅者连接到服务器时,发送的消息将丢失,不会保存在服务器。
对jms规范的理解:
jms
规范是sun提出的java的消息服务统一的api接口规范,规范、标准的好处就不用说了,java能走到今天,规范标准的制定可以说有很大的功劳吧。所
有提供java消息服务的软件提供者都必须针对这个接口实现。我们编写jms程序时,基本可以做到只针对接口编程,不用考虑是那个厂家实现,这是我们的代
码有了很大的灵活行,不绑定某个具体厂商。只要你的代码写的够好,完全可以不修改代码就直接部署到不同厂商的jms服务器上。
举个例子:编写一个基于ActiveMQ的jms程序时有这样的代码:
ActiveMQConnectionFactory factory = new
ActiveMQConnectionFactory("vm://localhost"
);
...
Queue queue = new
ActiveMQQueue("testQueue"
);
等,这样就在代码里绑死了ActiveMQ的api。要做到厂商无关性,应该使用jndi来取得工厂对象以及队列资源。
比如:
ConnectionFactory cf = (ConnectionFactory) ctx.lookup("connectionFactory");
...
Destination dest = (Queue) ctx.lookup("MyQueue");
注意接口也尽量使用jms的大的接口。当然这里需要提供jndi服务支持,ActiveMQ本身提供jndi服务,只要在classpath中有一个jndi.properties文件,在配置文件中对资源做一些配置就可以了
比如:
java.naming.factory.initial = org.apache.activemq.jndi.ActiveMQInitialContextFactory
connectionFactoryNames = connectionFactory, queueConnectionFactory, topicConnectionFactry
queue.MyQueue = zmQueue
topic.MyTopic = zmTopic
等。
对jms规范1.1的一些理解:
JMS 1.0.2 定义了两种类型的消息传递域(它们是相互独立的),即点对点和发布/订阅。JMS 的最新版本,即版本 1.1,JMS 统一了这两个域。如下图:有了 JMS 1.1,客户机就不再必须专门针对这个或那个域进行实现了。
JMS 公共 | PTP 域 | Pub/Sub 域 |
ConnectionFactory | QueueConnectionFactory | TopicConnectionFactory |
Connection | QueueConnection | TopicConnection |
Destination | Queue | Topic |
Session | QueueSession | TopicSession |
MessageProducer | QueueSender | TopicPublisher |
MessageConsumer | QueueReceiver | TopicSubscriber |
就是说,只使用JMS公共域的接口就可以完成jms程序编写。所以推荐尽量使用大的接口,增加代码的灵活性。
比如,写pub/sub方式的消息程序也可以这样:
Context ctx = new InitialContext();
ConnectionFactory factory = (ConnectionFactory) ctx
.lookup("connectionFactory");
Connection connection = factory.createConnection();
connection.start();
// 创建一个Topic
Destination topic = (Destination) ctx.lookup("MyTopic");
Session session = connection.createSession(false,
Session.AUTO_ACKNOWLEDGE);
MessageConsumer comsumer3 = session.createConsumer(topic);
Message msg = comsumer3.receive();
相关文章推荐
- 学习jms一些心得
- 两年软件开发学习心得
- OpenGL&&GLSL学习心得(1)
- 嵌入式每日学习心得2017.07.31
- 关于MySql中使用自定义函数的学习心得
- 持久层框架:ibatis学习心得,欢迎大家交流:wyf_cjl@sohu.com
- JavaWeb学习心得之Servlet(二)
- iptables学习心得
- Android Window PhoneWindow Activity学习心得--第三弹
- android新浪客户端学习心得(一)
- 我的MYSQL学习心得(一)
- 我的MYSQL学习心得(五)
- 学习了20个学时的C#.net,谈一些最简单的心得
- 3月21日学习与心得
- Android 中级学习心得
- css学习心得之一
- Unity5学习心得-旋转
- JMS学习十(Spring+ActiveMQ同步、异步)
- 新手学习java的心得体会
- 每日学习心得:CustomValidator验证控件验证用户输入的字符长度、Linq 多字段分组统计、ASP.NET后台弹出confirm对话框,然后点击确定,执行一段代码