WebSocket 整合

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

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

為何需要 Spring Session 和 WebSocket?

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

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

另一個問題是,根據 JSR-356,如果 HttpSession 超時,則任何使用該 HttpSession 和已驗證使用者建立的 WebSocket 都應強制關閉。這表示,如果我們在應用程式中積極聊天,且未使用 HttpSession,我們也會從對話中斷線。

WebSocket 用法

WebSocket 範例 提供了一個關於如何將 Spring Session 與 WebSocket 整合的工作範例。您可以遵循接下來幾個標題中描述的基本整合步驟,但我們鼓勵您在與自己的應用程式整合時,同時參考詳細的 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 我們擴充 AbstractSessionWebSocketMessageBrokerConfigurer,而不是實作 WebSocketMessageBrokerConfigurer
2 我們將 registerStompEndpoints 方法重新命名為 configureStompEndpoints

AbstractSessionWebSocketMessageBrokerConfigurer 在幕後做了什麼?

  • WebSocketConnectHandlerDecoratorFactory 作為 WebSocketHandlerDecoratorFactory 新增至 WebSocketTransportRegistration。這確保了觸發包含 WebSocketSession 的自訂 SessionConnectEventWebSocketSession 是結束 Spring Session 結束時仍開啟的任何 WebSocket 連線所必需的。

  • SessionRepositoryMessageInterceptor 作為 HandshakeInterceptor 新增至每個 StompWebSocketEndpointRegistration。這確保了將 Session 新增至 WebSocket 屬性,以啟用更新上次存取時間。

  • SessionRepositoryMessageInterceptor 作為 ChannelInterceptor 新增至我們的輸入 ChannelRegistration。這確保了每次接收到輸入訊息時,都會更新 Spring Session 的上次存取時間。

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