Spring BootでSockJSを使ったWebSocketの実装

本記事では、Spring BootでSockJSを利用したWebSocketの実装方法を説明します。 SockJSは、WebSocketが利用できない場合に自動的にフォールバックトランスポートを使用するため、さまざまなブラウザやネットワーク環境での接続性が向上します。

# サーバ側の実装

## 1. 依存関係の追加

`pom.xml` ファイルに `spring-boot-starter-websocket` 依存関係を追加します。

```xml:pom.xml
<dependency>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-starter-websocket</artifactId>
</dependency>
```

## 2. WebSocket設定クラスの作成

`WebSocketConfig` クラスを作成し、SockJSを有効にします。

```java:WebSocketConfig.java
package com.example.demo.webSocket;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.socket.WebSocketHandler;
import org.springframework.web.socket.config.annotation.EnableWebSocket;
import org.springframework.web.socket.config.annotation.WebSocketConfigurer;
import org.springframework.web.socket.config.annotation.WebSocketHandlerRegistry;

@Configuration
@EnableWebSocket
public class WebSocketConfig implements WebSocketConfigurer {

    @Override
    public void registerWebSocketHandlers(WebSocketHandlerRegistry registry) {
        registry.addHandler(messageHandler(), "/test")
                .setAllowedOrigins("<-- 自分のドメインを設定 -->") // CORSの設定
                .withSockJS(); // SockJSを有効にする
    }

    @Bean
    public WebSocketHandler messageHandler() {
        return new MessageHandler();
    }
}
```

## 3. WebSocketハンドラクラスの作成

`TextWebSocketHandler`を継承した`MessageHandler`クラスを作り、接続確立時、メッセージ受信時、接続終了時の操作を記述していきます。

```java:MessageHandler.java
package com.example.demo.webSocket;

import java.io.IOException;
import org.springframework.web.socket.CloseStatus;
import org.springframework.web.socket.TextMessage;
import org.springframework.web.socket.WebSocketSession;
import org.springframework.web.socket.handler.TextWebSocketHandler;
/**
 * WebSocketのHandler
 */
public class MessageHandler extends TextWebSocketHandler {
    /**
     * 接続確立
     */
    @Override
    public void afterConnectionEstablished(WebSocketSession session) throws Exception {
        System.out.println("WebSocketの接続が確立しました。");
    }
    /**
     * メッセージの送受信
     */
    @Override
    public void handleTextMessage(WebSocketSession session, TextMessage message) {
        System.out.println("メッセージ受信:" + message.getPayload());
        try {
            TextMessage outputMessage = new TextMessage("メッセージ返信：送信内容=" + message.getPayload());
            session.sendMessage(outputMessage);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
    /**
     * 接続終了
     */
    @Override
    public void afterConnectionClosed(WebSocketSession session, CloseStatus status) throws Exception {
        System.out.println("WebSocketの接続が終了しました。");
    }
}
```

# クライアント側の実装

## 1. HTMLファイルの作成

`index.html` ファイルを作成し、以下のコードを追加します。

```html:index.html
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>SockJS Example</title>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.6.0/jquery.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/sockjs-client/1.5.2/sockjs.min.js"></script>
    <script src="sockjs-websocket.js"></script>
</head>
<body>
    <h1>SockJS Example</h1>
    <input type="text" id="message" placeholder="メッセージを入力">
    <button onclick="sendMessage()">送信</button>
    <div id="messages"></div>
</body>
</html>
```

## 2. JavaScriptファイルの作成

`sockjs-websocket.js` ファイルを作成し、以下のコードを追加します。

```javascript:sockjs-websocket.js
$(function() {
    let socket;
    let messagesElement = $("#messages");

    // WebSocketへの接続
    function connectWebSocket() {
        socket = new SockJS("/test");

        // WebSocket接続確立時の処理
        socket.onopen = function (event) {
            console.log("WebSocket connected.");
        };

        // WebSocketでメッセージ受信時の処理
        socket.onmessage = function (event) {
            let messageElement = $("<div>").text("受信: " + event.data);
            messagesElement.append(messageElement);
        };

        // WebSocket接続終了時の処理
        socket.onclose = function (event) {
            console.log("WebSocket disconnected.");
        };
    }

    // メッセージ送信
    function sendMessage() {
        let messageInput = $("#message");
        let messageText = messageInput.val();
        if (socket && messageText) {
            socket.send(messageText);
            let messageElement = $("<div>").text("送信: " + messageText);
            messagesElement.append(messageElement);
            messageInput.val("");
        }
    }

    // 送信ボタンクリック時のイベント
    $("#sendButton").on("click", sendMessage);

    // ページ読み込み時にWebSocketへ接続
    connectWebSocket();
});
```

これで、Spring BootでSockJSを使ったWebSocketの実装が完了しました。`index.html` をブラウザで開き、メッセージを送信して受信ができることを確認してください。SockJSは、WebSocketが利用できない場合に自動的にフォールバックトランスポートを使用するため、さまざまなブラウザやネットワーク環境での接続性が向上します。