ActiveMQ使用记录

使用JMS的优点:

在系统集成中,我们可以使用RMI,Webservice等技术进行远程调用,但是他们都要求客户端程序处理完成后在返回给调用系统,这样就增加了调用系统的等待时间,对于一些不需要同步操作的系统会造成大的系统开销,如果使用jms,可以采用异步调用,把消息放到jms provider中即可,客户端不用等待回复.
   系统只负责把消息发送到服务端即可,不用管是否能被消费,这样减低了生产系统和消费系统的偶合.比如可以把发邮件的功能从系统中独立出来,专门做个系统发送邮件,邮件来源从jms服务器中取,这样就可以让多个系统共享发邮件的功能,不用重复开发.

JMS的一些基本概念:
1.PTP(点对点): 
• 每个消息只能有一个消费者。 
• 消息的生产者和消费者之间没有时间上的相关性。无论消费者在生产者发送消息的时候是否处于运行状态,它都可以提取消息。 
Pub/Sub(发布/订阅): 
• 每个消息可以有多个消费者。 
• 生产者和消费者之间有时间上的相关性。订阅一个主题的消费者只能消费自它订阅之后发布的消息。持久订阅允许消费者消费它在未处于激活状态时发送的消息。 

在点对点消息传递域中,目的地被成为队列(queue);在发布/订阅消息传递域中,目的地被成为主题(topic)。

.2。Session(会话):
Session.AUTO_ACKNOWLEDGE (常用): 会话自动确认 当消费者接收到消息,且执行完成(在没有异常的情况下) 系统会自动确认该客户端消费了该消息
Session.CLIENT_ACKNOWLEDGE:客户端确认 客户端通过调用消息的 acknowledge 方法手动确认成功接收一条消息 
Session.DUPS_OK_ACKNOWLEDGE:会话延迟消息的确认

3.消息持久化
在发送消息时,我们可以指定该消息是否持久化,默认持久化
producer.setDeliveryMode (DeliveryMode.PERSISTENT);
持久化就是当jms provider停止服务后,系统会把还没有发送的消息持久化到本地硬盘,当服务重启后,会重新加在消息到队列中,非持久化则反之, 相比较而言,持久化比较消耗性能,但是他能更好的保证消息被发送到客户端。

4.消息优先级
producer.setPriority (8);
消息的优先级从0(最低)到9(最高)有10种级别. 默认优先级为4 ,jms provider 会确保优先级高的消息会在优先级低的消息之前被传递,但并不保证会严格按照优先级的顺序来传递消息。

5.消息过期时间
producer.setTimeToLive(1000),参数单位:毫秒
消息默认情况下为0,即永不过期,如果设置了过期时间,那么在jms provider中超过了过期时间还没有发送出去的消息,系统会自动将其销毁掉

6.持久订阅
持久订阅只是针对Pub/Sub的消息模式 
为了确保发布/订阅应用程序能够接收到所有已发布的消息,在发布端可以使用 PERSISTENT 传递模式传输消息以确保消息不回在传输过程中丢失,而在订阅端则可以使用持久订阅来保证能够收到所有已发布的消息。
可以使用方法TopicSession.createDurableSubscriber 创建一个持久订阅者,持久订阅在任何时候仅能有一个订阅者.持久订阅是指,当客户端和服务端关闭连接以后,jms provider会保存那些没有被该客户端接收的消息,当持久端重新建立连接时,会将该消息发送给它

7。消息类型
TextMessage (文本消息类型)
BytesMessage (字节类型)
MapMessage (存储key,value类型)
ObjectMessage (对象类型,存储所有可以序列化的对象)
比较常用的是TextMessage和ObjectMessage

8.异步与同步接收
消息的异步接收:
异步接收是指当消息到达时,主动通知客户端,即当消息到达时转发到客户端。JMS客户端可以通过注册一个实现MessageListener接口的对象到MessageConsumer,这样,每当消息到达时,JMS Provider 会调用MessageListener中的onMessage 方法。所以需要创建一个消息监听器,然后注册一个或多个使用MessageConsumer的JMS MessageListener接口。会话(主题或队列)负责产生某些消息,这些消息被传送到使用onMessage方法的监听者那里;
客户可以为消费者注册一个消息监听器,以定义在消息到达时所采取的动作

消息的同步接收
jms同步接受消息的功能(客户端必须请求每个消息),通过调用消费者的receive方法从目的地中显式提取消息,receive方法可以一直阻塞到消息到达,同步接收是指客户端主动去接收消息,JMS 客户端可以采用MessageConsumer的receive方法去接收下一个消息。
接收消息的方法还有一个"不等待"的版本,使用这个方法时QueueReceiver对象检查是否有消息之后立即返回,将控制交还给程序。 
TextMessage message = queueReceiver.receiveNoWait ();



研究心得:
PTP(点对点):每个消息只能有一个消费者,也就是一条消息只能消费一次。
持久化:默认持久化,设置非持久化时,关闭会话,消息自动销毁。
注:不能同时设置非持久化和消息过期,当设置非持久化,消息1000毫秒过期时,则冲突,按设置消息过期时间为准。
消息过期:setTimeToLive(1000),默认参数为0毫秒,永不过期。
Session(会话):
当设定事务为true时,一旦commit()执行,它就确认收到了在此之前尚未提交的所有消息;消息发送方的情况也相似。
Pub/Sub(发布/订阅):
持久化订阅。(订阅后关闭连接,下一次打开能接收到订阅的信息)。
订阅类要设置connection.SetClientID ("clientID001");
MessageConsumer messageConsumer = 
consumer.getSession ().createDurableSubscriber ((Topic) destination, "mySub");
测试一:
A、 先启动Publisher类
B、 再启动Consumer类
C、 结果无任何记录被订阅
测试二:
A、 先启动Consumer类,让Comsumer在相关主题上进行订阅
B、 停止Consumer类,再启动Publisher类
C、 待Publisher类运行完成后,再启动Consumer类
D、 结果发现相应主题的信息被订阅
注:也就是说订阅和发布先预先设置一个主题,订阅者订阅后,关闭程序,发布者看到有人订阅,执行发布消息,订阅者下次登录时可以接受到发布的消息。
消息的同步接收:
JMS 客户端可以采用MessageConsumer的receive方法去接收下一个消息。
接收完一条后必须关闭客户端相应连接才能接收下一条发送过来的消息。
消息类型示例:
// Text Message
TextMessage textMsg = session.createTextMessage ();
textMsg.setText("消息内容文本");
// Map Message
MapMessage mapMsg = session.createMapMessage();
mapMsg.setInt (BookCatalogNumber, 100);
mapMsg.setString(BookTitle, "书籍题目");
mapMsg.setLong (BookCost, 50.00);
String bookTitle = mapMsg.getString ("BookTitle");
// Object Message
ObjectMessage objectMsg = session.createObjectMessage ();
Book book = new Book("WinSocks 2.0");
objectMsg.setObject (book);

ActiveMQ应用:(文件传输)
这里使用的 MQ 中间件是开源的 ActiveMQ,可以不采用 BytesMessage 来按字节传送文件,而是 ActiveMQ 为我们提供了org.apache.activemq.BlobMessage,可以用它来传送大对象。