|
对于最新的稳定版本,请使用 Spring Framework 7.0.6! |
用户目的地
应用程序可以发送针对特定用户的消息,Spring 的 STOMP 支持会识别以 /user/ 开头的目标地址。
例如,客户端可能会订阅 /user/queue/position-updates 目标地址。
UserDestinationMessageHandler 会处理此目标地址,并将其转换为与用户会话唯一的目标地址(例如 /queue/position-updates-user123)。
这提供了订阅通用名称目标地址的便利性,同时确保与其他订阅相同目标地址的用户不会发生冲突,从而确保每个用户都能收到唯一的股票持仓更新。
在处理用户目标时,需要按照 启用 STOMP 中所示配置代理和应用程序目标前缀,否则代理会处理本应由 UserDestinationMessageHandler 处理的 "/user" 前缀消息。 |
在发送端,消息可以发送到如/user/{username}/queue/position-updates这样的目标,该目标又通过UserDestinationMessageHandler转换为一个或多个目标,每个目标对应与用户相关联的一个会话。这使得应用程序中的任何组件都可以发送针对特定用户的消息,而无需知道除了用户名和通用目标之外的其他信息。这也通过注解和消息模板得到支持。
一个消息处理方法可以通过<code>0</code>注解(也支持在类级别上使用,以共享一个共同的目标)将消息发送给与正在处理的消息相关联的用户,如下例所示:
@Controller
public class PortfolioController {
@MessageMapping("/trade")
@SendToUser("/queue/position-updates")
public TradeResult executeTrade(Trade trade, Principal principal) {
// ...
return tradeResult;
}
}
如果用户有多个会话,默认情况下,所有订阅到给定目标的会话都会被定位。但是,有时可能需要仅定位正在处理的消息发送的会话。你可以通过将 broadcast 属性设置为 false 来实现,如下例所示:
@Controller
public class MyController {
@MessageMapping("/action")
public void handleAction() throws Exception{
// raise MyBusinessException here
}
@MessageExceptionHandler
@SendToUser(destinations="/queue/errors", broadcast=false)
public ApplicationError handleException(MyBusinessException exception) {
// ...
return appError;
}
}
虽然用户目标通常意味着已认证的用户,但并非严格必需。
与已认证用户无关的WebSocket会话
可以订阅用户目标。在这种情况下,@SendToUser注解
与broadcast=false的行为完全相同(即,仅针对正在处理的消息发送的会话)。 |
您可以通过从任何应用程序组件注入由Java配置或XML命名空间创建的<code>0</code>,将消息发送到用户目标。 (如果需要与<code>2</code>进行限定,bean名称为<code>1</code>。)下面的示例显示了如何操作:
@Service
public class TradeServiceImpl implements TradeService {
private final SimpMessagingTemplate messagingTemplate;
@Autowired
public TradeServiceImpl(SimpMessagingTemplate messagingTemplate) {
this.messagingTemplate = messagingTemplate;
}
// ...
public void afterTradeExecuted(Trade trade) {
this.messagingTemplate.convertAndSendToUser(
trade.getUserName(), "/queue/position-updates", trade.getResult());
}
}
当您使用外部消息代理的用户目标时,应查看代理的文档,了解如何管理不活跃的队列,以便在用户会话结束时删除所有唯一的用户队列。例如,RabbitMQ 在使用诸如 /exchange/amq.direct/position-updates 的目标时会创建自动删除的队列。
因此,在这种情况下,客户端可以订阅 /user/exchange/amq.direct/position-updates。
同样,ActiveMQ 也有
配置选项
用于清除不活跃的目标。 |
在多应用程序服务器的场景中,由于用户连接到不同的服务器,用户目标可能无法解析。在这种情况下,您可以配置一个目标以广播未解析的消息,以便其他服务器有机会尝试。这可以通过Java配置中的userDestinationBroadcast属性和XML中的message-broker元素的user-destination-broadcast属性来完成。