使用者目的地
應用程式可以傳送針對特定使用者的訊息,Spring 的 STOMP 支援為此目的識別以 /user/ 為字首的目的地。例如,客戶端可以訂閱 /user/queue/position-updates 目的地。UserDestinationMessageHandler 處理此目的地並將其轉換為使用者會話獨有的目的地(例如 /queue/position-updates-user123)。這提供了訂閱通用命名目的地的便利,同時確保與其他訂閱同一目的地的使用者沒有衝突,以便每個使用者都可以接收唯一的股票倉位更新。
在使用使用者目的地時,務必配置代理和應用程式目的地字首,如啟用 STOMP 中所示,否則代理將處理應僅由 UserDestinationMessageHandler 處理的 "/user" 字首訊息。 |
在傳送端,可以將訊息傳送到 /user/{username}/queue/position-updates 等目的地,然後由 UserDestinationMessageHandler 翻譯成一個或多個目的地,每個目的地對應一個與使用者關聯的會話。這使得應用程式中的任何元件都可以傳送針對特定使用者的訊息,而無需知道除其名稱和通用目的地之外的任何資訊。這也透過註解和訊息模板支援。
訊息處理方法可以透過 @SendToUser 註解向與正在處理的訊息關聯的使用者傳送訊息(也支援在類級別共享公共目的地),示例如下:
@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 名稱空間建立的 SimpMessagingTemplate。(如果需要與 @Qualifier 一起進行限定,則 bean 名稱為 brokerMessagingTemplate。)示例如下:
@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());
}
}
當您將使用者目的地與外部訊息代理一起使用時,您應該查閱代理文件,瞭解如何管理不活躍的佇列,以便在使用者會話結束時刪除所有唯一的使用者佇列。例如,當您使用 /exchange/amq.direct/position-updates 等目的地時,RabbitMQ 會建立自動刪除佇列。因此,在這種情況下,客戶端可以訂閱 /user/exchange/amq.direct/position-updates。同樣,ActiveMQ 有用於清除不活躍目的地的配置選項。 |
在多應用伺服器場景中,使用者目的地可能未解析,因為使用者連線到不同的伺服器。在這種情況下,您可以配置一個目的地來廣播未解析的訊息,以便其他伺服器有機會嘗試。這可以透過 Java 配置中 MessageBrokerRegistry 的 userDestinationBroadcast 屬性和 XML 中 message-broker 元素的 user-destination-broadcast 屬性來完成。