返回介绍

18.4.1 在控制器中处理用户的消息

发布于 2024-08-17 00:45:49 字数 2340 浏览 0 评论 0 收藏 0

如前所述,在控制器的@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 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据
    我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
    原文