使用者目的地

應用程式可以傳送以特定使用者為目標的訊息,而 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 組態中 MessageBrokerRegistryuserDestinationBroadcast 屬性和 XML 中 message-broker 元素的 user-destination-broadcast 屬性來完成。