- 作者简介
- 内容提要
- 关于本书
- 路线图
- 代码规范与下载
- 作者在线
- 封面插图简介
- 前言
- 译者序
- 致谢
- 第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 开发
18.4.1 在控制器中处理用户的消息
如前所述,在控制器的@MessageMapping或@SubscribeMapping方法中,处理消息时有两种方式了解用户信息。在处理器方法中,通过简单地添加一个Principal参数,这个方法就能知道用户是谁并利用该信息关注此用户相关的数据。除此之外,处理器方法还可以使用@SendToUser注解,表明它的返回值要以消息的形式发送给某个认证用户的客户端(只发送给该客户端)。
为了阐述该功能,让我们编写一个控制器方法,它会根据传入的消息创建新的Spittle对象,并发送一个回应,表明Spittle已经保存成功。如果你觉得这个场景很熟悉的话,那是因为在第16章我们以REST端点的形式实现了它。但是REST请求是同步的,当服务器处理的时候,客户端必须要等待。通过将Spittle发送为STOMP消息,我们可以充分发挥STOMP消息异步的优势。
考虑如下的handleSpittle()方法,它会处理传入的消息并将其存储为Spittle:
可以看到,handleSpittle()方法接受Principal对象和SpittleForm对象作为参数。它使用这两个对象创建一个Spittle实例并借助SpittleRepository将实例保存起来。最后,它返回一个新的Notification,表明Spittle已经保存成功。
当然,比起方法内部的功能,这个方法体外部所做事情也许更让我们感兴趣。因为这个方法使用了@MessageMapping注解,因此当有发往“/app/spittle”目的地的消息到达时,该方法就会触发,并且会根据消息创建SpittleForm对象,如果用户已经认证过的话,将会根据STOMP帧上的头信息得到Principal对象。
但是,需要特别关注的是,返回的Notification到哪里去了。@SendToUser注解指定返回的Notification要以消息的形式发送到“/queue/notifications”目的地上。在表面上,“/queue/notifications”并没有与特定用户关联。但因为这里使用的是@SendToUser注解而不是@SendTo,所以就会发生更多的事情了。
为了理解Spring如何发布消息,让我们先退后一步,看一下针对控制器方法发布Notification对象的目的地,客户端该如何进行订阅。考虑如下的这行JavaScript代码,它订阅了一个用户特定的目的地:
注意,这个目的地使用了“/user”作为前缀,在内部,以“/user”作为前缀的目的地将会以特殊的方式进行处理。这种消息不会通过AnnotationMethodMessageHandler(像应用消息那样)来处理,也不会通过SimpleBrokerMessageHandler或StompBrokerRelayMessageHandler(像代理消息那样)来处理,以“/user”为前缀的消息将会通过UserDestinationMessageHandler进行处理,如图18.4所示。
图18.4 用户消息流会通过UserDestinationMessageHandler进行处理,它会将消息重路由到某个用户独有的目的地上
UserDestinationMessageHandler的主要任务是将用户消息重新路由到某个用户独有的目的地上。在处理订阅的时候,它会将目标地址中的“/user”前缀去掉,并基于用户的会话添加一个后缀。例如,对“/user/queue/notifications”的订阅最后可能路由到名为“/queue/notifications-user6hr83v6t”的目的地上。
在我们的样例中,handleSpittle()方法使用了@SendToUser("/queue/notifications")注解。这个新的目的地以“/queue”作为前缀,根据配置,这是StompBrokerRelayMessageHandler(或SimpleBrokerMessageHandler)要处理的前缀,所以消息接下来会到达这里。最终,客户端会订阅这个目的地,因此客户端会收到Notification消息。
在控制器方法中,@SendToUser注解和Principal参数是很有用的。但是在程序清单18.8中,我们看到借助消息模板,可以在应用的任何位置发送消息。接下来看一下如何使用SimpMessagingTemplate将消息发送给特定用户。
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论