WebSocket 整合

Spring Session 提供與 Spring 的 WebSocket 支援的透明整合。

Spring Session 的 WebSocket 支援僅與 Spring 的 WebSocket 支援配合使用。具體來說,它不能直接使用 JSR-356,因為 JSR-356 沒有攔截傳入 WebSocket 訊息的機制。

為何選擇 Spring Session 和 WebSockets?

那麼,當我們使用 WebSockets 時,為何需要 Spring Session?

考慮一個電子郵件應用程式,其大部分工作透過 HTTP 請求完成。但是,其中還嵌入了一個透過 WebSocket API 工作的聊天應用程式。如果使用者正在與某人積極聊天,我們不應該讓 HttpSession 超時,因為這將是一種非常糟糕的使用者體驗。然而,JSR-356 正是這樣做的。

另一個問題是,根據 JSR-356,如果 HttpSession 超時,則應強制關閉使用該 HttpSession 和經過身份驗證的使用者建立的任何 WebSocket 連線。這意味著,如果我們在應用程式中積極聊天但沒有使用 HttpSession,我們也會斷開與對話的連線。

WebSocket 使用

WebSocket 示例提供了一個關於如何將 Spring Session 與 WebSockets 整合的可工作的示例。您可以遵循接下來的幾個標題中描述的基本整合步驟,但我們鼓勵您在與自己的應用程式整合時參考詳細的 WebSocket 指南。

HttpSession 整合

在使用 WebSocket 整合之前,您應首先確保 HttpSession 整合工作正常。

Spring 配置

在典型的 Spring WebSocket 應用程式中,您會實現 WebSocketMessageBrokerConfigurer。例如,配置可能如下所示

@Configuration
@EnableScheduling
@EnableWebSocketMessageBroker
public class WebSocketConfig implements WebSocketMessageBrokerConfigurer {

	@Override
	public void registerStompEndpoints(StompEndpointRegistry registry) {
		registry.addEndpoint("/messages").withSockJS();
	}

	@Override
	public void configureMessageBroker(MessageBrokerRegistry registry) {
		registry.enableSimpleBroker("/queue/", "/topic/");
		registry.setApplicationDestinationPrefixes("/app");
	}

}

我們可以更新配置以使用 Spring Session 的 WebSocket 支援。以下示例顯示瞭如何做到這一點

src/main/java/samples/config/WebSocketConfig.java
@Configuration
@EnableScheduling
@EnableWebSocketMessageBroker
public class WebSocketConfig extends AbstractSessionWebSocketMessageBrokerConfigurer<Session> { (1)

	@Override
	protected void configureStompEndpoints(StompEndpointRegistry registry) { (2)
		registry.addEndpoint("/messages").withSockJS();
	}

	@Override
	public void configureMessageBroker(MessageBrokerRegistry registry) {
		registry.enableSimpleBroker("/queue/", "/topic/");
		registry.setApplicationDestinationPrefixes("/app");
	}

}

要接入 Spring Session 支援,我們只需更改兩項內容

1 不再實現 WebSocketMessageBrokerConfigurer,而是擴充套件 AbstractSessionWebSocketMessageBrokerConfigurer
2 我們將 registerStompEndpoints 方法重新命名為 configureStompEndpoints

AbstractSessionWebSocketMessageBrokerConfigurer 在幕後做了什麼?

  • WebSocketConnectHandlerDecoratorFactory 被新增為 WebSocketTransportRegistration 的一個 WebSocketHandlerDecoratorFactory。這確保會觸發一個包含 WebSocketSession 的自定義 SessionConnectEvent。當 Spring Session 結束時,WebSocketSession 對於終止任何仍然開啟的 WebSocket 連線是必要的。

  • SessionRepositoryMessageInterceptor 被新增為每個 StompWebSocketEndpointRegistration 的一個 HandshakeInterceptor。這確保 Session 被新增到 WebSocket 屬性中,以便更新最後訪問時間。

  • SessionRepositoryMessageInterceptor 被新增為我們的入站 ChannelRegistration 的一個 ChannelInterceptor。這確保每當接收到入站訊息時,我們的 Spring Session 的最後訪問時間都會得到更新。

  • WebSocketRegistryListener 被建立為一個 Spring bean。這確保我們擁有所有 Session ID 與相應的 WebSocket 連線的對映。透過維護此對映,當 Spring Session (HttpSession) 結束時,我們可以關閉所有 WebSocket 連線。