使用者目的地
應用程式可以傳送以特定使用者為目標的訊息,而 Spring 的 STOMP 支援可識別以此為目的,以 /user/
為前綴的目的地。例如,用戶端可能會訂閱 /user/queue/position-updates
目的地。UserDestinationMessageHandler
處理此目的地,並將其轉換為使用者會話唯一的目的地 (例如 /queue/position-updates-user123
)。這提供了訂閱通用命名目的地的便利性,同時確保與訂閱相同目的地的其他使用者沒有衝突,以便每位使用者都可以收到獨特的股票倉位更新。
使用使用者目的地時,重要的是要組態 Broker 和應用程式目的地前綴,如 啟用 STOMP 中所示,否則 Broker 將處理應僅由 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());
}
}
當您將使用者目的地與外部訊息 Broker 一起使用時,您應該查看 Broker 文件,了解如何管理非活動佇列,以便在使用者會話結束時移除所有唯一使用者佇列。例如,當您使用諸如 /exchange/amq.direct/position-updates 之類的目的地時,RabbitMQ 會建立自動刪除佇列。因此,在這種情況下,用戶端可以訂閱 /user/exchange/amq.direct/position-updates 。同樣地,ActiveMQ 具有 組態選項,用於清除非活動目的地。 |
在多應用程式伺服器情境中,使用者目的地可能仍未解析,因為使用者連線到不同的伺服器。在這種情況下,您可以組態目的地以廣播未解析的訊息,以便其他伺服器有機會嘗試。這可以透過 Java 組態中 MessageBrokerRegistry
的 userDestinationBroadcast
屬性和 XML 中 message-broker
元素的 user-destination-broadcast
屬性來完成。