1、15.1 异步通信方式与JMS15.1.1 异步通信方式异步通信方式(1)点对点方式点对点方式:适用于发送方和接收方为一对一的适用于发送方和接收方为一对一的情形。发送方将消息发送到消息队列情形。发送方将消息发送到消息队列,接收方从队列中接收方从队列中取出消息。队列保存着所有发送给它的消息取出消息。队列保存着所有发送给它的消息,直到这个直到这个消息被取走或者消息已经过期。如果多个消费者在监消息被取走或者消息已经过期。如果多个消费者在监听同一个队列听同一个队列,但一条消息只有一个消费者会接收到。但一条消息只有一个消费者会接收到。(2)发布发布/订阅方式订阅方式:通过一个称为主题的虚拟通道进行交通过
2、一个称为主题的虚拟通道进行交换消息。发布者将消息发送到指定的主题,消息服务换消息。发布者将消息发送到指定的主题,消息服务器负责通知该主题的所有订阅者。多个发布者可以向器负责通知该主题的所有订阅者。多个发布者可以向一个主题发布消息一个主题发布消息,多个订阅者可以从一个主题订阅消多个订阅者可以从一个主题订阅消息。息。15.1.2 JMS(Java消息服务)15.2 ActiveMQ消息队列服务器的配置ActiveMQ的安装配置。的安装配置。(1)从)从ActiveMQ的官方网站的官方网站http:/activemq.apache.org/下下载载ActiveMQ。(2)在本地解压后,双击)在本地解
3、压后,双击bin目录下目录下activemq.bat文件即可启动文件即可启动ActiveMQ。(3)在浏览器中输入)在浏览器中输入 http:/localhost:8161/admin/,就,就可以打开可以打开ActiveMQ的网页图形化管理界面。可以通过该管理界的网页图形化管理界面。可以通过该管理界面进行队列和主题的管理。面进行队列和主题的管理。(4)点击页面的点击页面的Queue超链,进入超链,进入Queue管理界面,新建一管理界面,新建一个队列个队列“TestQueue”。如图。如图15-2所示。随着应用的执行,可以所示。随着应用的执行,可以刷新该页面观察队列的消息处理情况。刷新该页面观
4、察队列的消息处理情况。基于主题的目标使用基于主题的目标使用ActiveMQTopic进行创建,通过构造参数进行创建,通过构造参数传递主题。传递主题。以下以下Bean定义目标的主题名为定义目标的主题名为“SOA”。基于队列的目标使用基于队列的目标使用ActiveMQQueue进行创建进行创建.以下以下Bean定义了一个名为定义了一个名为TestQueue的队列作为目标。的队列作为目标。15.3 Spring JMS简介 Spring JMS定义了一系列接口和类,对发送的消息创建、消息转定义了一系列接口和类,对发送的消息创建、消息转换、消息目标解析以及消息发送与接收方法进行了有效封装。换、消息目标
5、解析以及消息发送与接收方法进行了有效封装。org.springframework.jms.core 包提供了在包提供了在 Spring 中使用中使用 JMS 的核心功能,其中,的核心功能,其中,JmsTemplate处理资源的创建和释放,简化处理资源的创建和释放,简化了访问目标(队列或主题)和向指定目标发布消息时了访问目标(队列或主题)和向指定目标发布消息时JMS的使用。的使用。org.springframework.jms.support包提供转换包提供转换 JMSException 的功能,的功能,JMSException是是Spring框架所有框架所有JMS异常的抽象基类;异常的抽象基类
6、;support包的包的converter子包提供子包提供 MessageConverter 抽象,以在抽象,以在 Java 对象和对象和 JMS 消息之间进行转换;消息之间进行转换;support包的包的destination子包子包提供管理提供管理 JMS 目标的不同策略。目标的不同策略。org.springframework.jms.connection包提供适合在独立应用程包提供适合在独立应用程序中使用的序中使用的 ConnectionFactory 实现,也即实现,也即SingleConnectionFactory,多个,多个 JmsTemplate 调用可以使用同一调用可以使用同一
7、个连接以跨越多个事务。个连接以跨越多个事务。15.3.1 用JMSTemplate进行消息发送和接收JmsTemplate的几个常用方法方法名称方法名称功能功能sendsend发送消息至指定的目标。可通过设置发送消息至指定的目标。可通过设置JmsTemplateJmsTemplate的的defaultDestinationdefaultDestination属性指定默认目标。属性指定默认目标。receivereceive用于同步方式从指定目标接收消息,可通过设置用于同步方式从指定目标接收消息,可通过设置JmsTemplateJmsTemplate的的receiveTimeoutreceiveT
8、imeout属性指定超时时间。属性指定超时时间。convertAndSendconvertAndSend委托委托MessageConverterMessageConverter实例处理转换实例处理转换,并发送消息,并发送消息至指定目标。至指定目标。receiveAndConvertreceiveAndConvert从默认或指定的目标接收消息,并将消息转换为从默认或指定的目标接收消息,并将消息转换为JavaJava对象。对象。15.3.2 Java对象到消息转换接口借助消息转换器,借助消息转换器,JmsTemplate提供了如下方提供了如下方法发送法发送Java对象到目标。对象到目标。conve
9、rtAndSend(Object message):发送:发送对象到默认目标。对象到默认目标。convertAndSend(Destination destination,Object message):发送对象到指定目标。:发送对象到指定目标。15.4 消息发送/接收样例15.4.1 发送消息发送消息Bean的设计的设计public class MsgProducer private JmsTemplate template;private Destination destination;/template和和destination的的setter及及getter方法略方法略public v
10、oid send(final String msg)template.send(destination,new MessageCreator()public Message createMessage(Session session)throws JMSException return session.createTextMessage(msg););如果利用消息转换器发送,则如果利用消息转换器发送,则send方法内代码还可简化,只需要如下一行即可。方法内代码还可简化,只需要如下一行即可。template.convertAndSend(destination,msg);15.4.2 应用配置1
11、5.4.3 接收消息Bean的设计消息接收有两种方法消息接收有两种方法一种是同步方式,采用一种是同步方式,采用JmsTemplate的的receive()方法,默认情况下,调用方法,默认情况下,调用receive方方法之后将会等待消息发送至法之后将会等待消息发送至destination。另一种是异步方式,它是最常用的方式,采用另一种是异步方式,它是最常用的方式,采用事件驱动。事件驱动。JMS提供了消息监听器接口提供了消息监听器接口MessageListener来实现消息的异步接收,来实现消息的异步接收,该接口中只含该接口中只含onMessage方法,消息到来时方法,消息到来时将触发执行该方法。
12、将触发执行该方法。SSpring通过通过listenerContainer(消息监听容器消息监听容器)来包裹来包裹MessageListener。Spring提供了三种消息监听容器,它们是提供了三种消息监听容器,它们是AbstractMessageListenerContainer 的子类。的子类。SimpleMessageListenerContainer:最简单的消息监听容器,:最简单的消息监听容器,它在启动时创建固定数量的它在启动时创建固定数量的JMS session,并在容器的整个生命,并在容器的整个生命周期中使用这些周期中使用这些session。该容器不能动态适应运行时的要求,。该容
13、器不能动态适应运行时的要求,也不能参与消息接收的事务处理。也不能参与消息接收的事务处理。DefaultMessageListenerContainer:是使用的最多的消息监:是使用的最多的消息监听容器。它可以动态适应运行时的要求,也可以参与事务管理。听容器。它可以动态适应运行时的要求,也可以参与事务管理。ServerSessionMessageListenerContainer:该容器用:该容器用JMS ServerSessionPool SPI动态管理动态管理JMS Session,可以获得运,可以获得运行时动态调优功能。行时动态调优功能。【程序清单15-3】文件名为Receiver.jav
14、apublic class Receiver implements MessageListener public void onMessage(Message message)if(message instanceof TextMessage)TextMessage text=(TextMessage)message;try System.out.println(收到消息收到消息:+text.getText();catch(JMSException e)config.xml15.4.4 应用环境的装载与消息发送测试public static void main(String args)throws Exception ApplicationContext context=new ClassPathXmlApplicationContext(config.xml);MsgProducer sender=(MsgProducer)context.getBean(sender);for(int k=0;k 5;k+)sender.send(第第 +k+条消息!条消息!);Thread.sleep(1000);