- 作者简介
- 内容提要
- 关于本书
- 路线图
- 代码规范与下载
- 作者在线
- 封面插图简介
- 前言
- 译者序
- 致谢
- 第1部分 Spring 的核心
- 第1章 Spring 之旅
- 第2章 装配 Bean
- 第3章 高级装配
- 第4章 面向切面的 Spring
- 第2部分 Web 中的 Spring
- 第5章 构建 Spring Web 应用程序
- 第6章 渲染 Web 视图
- 第7章 Spring MVC 的高级技术
- 第8章 使用 Spring Web Flow
- 第9章 保护 Web 应用
- 第3部分 后端中的 Spring
- 第10章 通过 Spring 和 JDBC 征服数据库
- 第11章 使用对象-关系映射持久化数据
- 第12章 使用 NoSQL 数据库
- 第13章 缓存数据
- 第14章 保护方法应用
- 第4部分 Spring 集成
- 第15章 使用远程服务
- 第16章 使用 Spring MVC 创建 REST API
- 第17章 Spring消息
- 第18章 使用 WebSocket 和 STOMP 实现消息功能
- 第19章 使用 Spring 发送 Email
- 第20章 使用 JMX 管理 Spring Bean
- 第21章 借助 Spring Boot 简化 Spring 开发
17.2.3 创建消息驱动的 POJO
在学校时的一个暑假期间,我得到了在黄石国家公园工作的机会。这个工作并不是公园巡逻者或者开关老忠实泉(Old Faithful)这样的高级工作,而是在老忠实泉酒店进行更换床单、清理卫生间以及打扫地板等家务工作。虽然不是很吸引人,但至少我是在这个世界上最美丽的地方工作。
每天工作之后,我都到当地的邮局看看是否有我的邮件。我已经离家好几个星期了,所以能收到学校朋友的来信或者明信片是一件非常美好的事情。我没有自己的邮箱,所以必须走着去邮局,并询问坐在柜台后的工作人员是否有我的邮件。接着就是开始等待。
要知道,柜台后的那个人大约有195岁[1]了。像他这个岁数的人,走动起来很费时间。他从椅子上站起来,慢慢走过地板,消失在隔墙后。过了一会儿,他出现了,慢慢回到柜台,坐到椅子上,然后看着我说:“今天没有邮件”。
JmsTemplate的receive()方法与这个上了年纪的邮局雇员很像。当我们调用receive()方法时,JmsTemplate会查看队列或主题中是否有消息,直到收到消息或者等待超时才会返回。这期间,应用无法处理任何事情,只能等待是否有消息。如果应用能够继续进行其他业务处理,当消息到达时再去通知它,不是更好吗?
EJB2规范的一个重要内容是引入了消息驱动bean(message-driven bean,MDB)。MDB是可以异步处理消息的EJB。换句话说,MDB将JMS目的地中的消息作为事件,并对这些事件进行响应。而与之相反的是,同步消息接收者在消息可用前会一直处于阻塞状态。
MDB是EJB中的一个亮点。即使那些狂热的EJB反对者也认为MDB可以优雅地处理消息。EJB 2 MDB的唯一缺点是它们必须要实现java.ejb.MessageDriven-Bean。此外,它们还必须实现一些EJB生命周期的回调方法。简而言之,EJB 2 MDB 不是纯的POJO。
在EJB 3规范中,MDB进一步简化了,使其更像POJO。我们不再需要实现MessageDrivenBean接口,而是实现更通用的javax.jms.MessageListener接口,并使用@MessageDriven注解标注MDB。
Spring 2.0提供了它自己的消息驱动bean来满足异步接收消息的需求,这种形式与EJB 3的MDB很相似。在本节中,我们将学习到Spring是如何使用消息驱动POJO(我们将其简称为MDP)来支持异步接收消息的。
创建消息监听器
如果使用EJB的消息驱动模型来创建Spittle的提醒处理器,我们需要使用@MessageDriven注解进行标注。即使它不是严格要求的,但EJB规范还是建议MDB实现MessageListener接口。Spittle的提醒处理器最终可能是这样的:
想象一下,如果消息驱动组件不需要实现MessageListener接口,世界将是多么的简单。在这里,天是蔚蓝的,鸟儿唱着我们喜欢的歌,我们不再需要实现onMessage()方法或者注入Messge DrivenContext。
好吧,可能EJB 3规范所要求的MDB也算不上太麻烦。但是事实上,SpittleAlertHandler的EJB 3实现太依赖于EJB的消息驱动API,并不是我们所希望的POJO。理想情况下,我们希望提醒处理器能够处理消息,但是不用编码,就好像它知道应该做什么。
Spring提供了以POJO的方式处理消息的能力,这些消息来自于JMS的队列或主题中。例如,基于POJO实现SpittleAlertHandler就足以做到这一点。
程序清单17.5 Spring MDP异步接收和处理消息
虽然改变天空的颜色和训练鸟儿歌唱超出了Spring的范围,但程序清单17.5所展示的现实与我描绘的理想世界非常接近。我们稍后会编写handleSpittleAlert()方法的具体内容。现在,程序清单 17.5所展示的SpittleAlertHandler没有任何JMS的痕迹。从任意一个角度观察,它都是一个纯粹的POJO。它仍然可以像EJB那样处理消息,只不过它还需要一些Spring的配置。
配置消息监听器
为POJO赋予消息接收能力的诀窍是在Spring中把它配置为消息监听器。Spring的jms命名空间为我们提供了所需要的一切。首先,让我们先把处理器声明为bean:
然后,为了把SpittleAlertHandler转变为消息驱动的POJO,我们需要把这个bean声明为消息监听器:
在这里,我们在消息监听器容器中包含了一个消息监听器。消息监听器容器(message listener container)是一个特殊的bean,它可以监控JMS目的地并等待消息到达。一旦有消息到达,它取出消息,然后把消息传给任意一个对此消息感兴趣的消息监听器。如图17.7展示了这个交互过程。
图17.7 消息监听器容器监听队列和主题。
当消息到达时,消息将转给消息监听器(例如消息驱动的POJO)
为了在Spring中配置消息监听器容器和消息监听器,我们使用了Spring jms命名空间中的两个元素。<jms:listener-container>中包含了<jms:listener>元素。这里的connection-factory属性配置了对connectionFactory的引用,容器中的每个<jms:listener>都使用这个连接工厂进行消息监听。在本示例中,connection-factory属性可以移除,因为该属性的默认值就是connectionFactory。
对于<jms:listener>元素,它用于标识一个bean和一个可以处理消息的方法。为了处理Spittle提醒消息,ref元素引用了spittleHandler bean。当消息到达spitter.alert.queue队列(通过destination属性配置)时,spittleHandlerbean的handleSpittleAlert()方法(通过method属性指定的)会被触发。
值得一提的是,如果ref属性所标示的bean实现了MessageListener,那就没有必要再指定method属性了,默认就会调用onMessage()方法。
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论