https://a.storyblok.com/f/270183/614640/4642d493ac/websocket-server-spark.png

Spark FrameworkでWebSocketサーバーを作成する

最終更新日 May 3, 2021

所要時間:1 分

ウェブソケットは、サーバーとブラウザー間の通信を可能にするプロトコルである。通信が双方向かつリアルタイムであるため、RESTful HTTPよりも優れている。このため、クライアントが定期的に更新をポーリングする代わりに、サーバーがいつでもクライアントに通知することができます。

この連載では、JavaでWebSocketサーバーを作成する3つの異なる方法を紹介します。 Spring BootSpark Frameworkそして Java API for WebSockets.

前提条件

使用するのは Gradleを使います。

さらに、JDKのコピーがインストールされていることを確認する必要がある。このチュートリアルではJDK 8を使用します。

SparkフレームワークによるWebSocket

スパークは、JavaやKotlinのウェブアプリケーションを作成するためのマイクロフレームワークである。

プロジェクトの作成

Gradleを使って新しいJavaアプリケーションを初期化します。以下のコマンドを使用してプロジェクト用のディレクトリを作成し、そのディレクトリに移動してアプリケーションを初期化します:

mkdir websocket-spark-framework cd websocket-spark-framework gradle init --type=java-application

Spark の依存関係を追加する

以下の依存関係を dependenciesブロックに追加する。 build.gradle:

compile 'com.sparkjava:spark-core:2.7.2'

とは異なる Spring BootでWebSocketサーバーを作るとは異なり、Sparkを使ったWebSocketは組み込みの Jettyサーバーでしか動作しないので、HTTPルートの前にパスとハンドラを定義する必要があります。

WebSocketハンドラの作成

WebSocketメッセージにはテキストとバイナリの両方があります。この両方のメッセージを処理できるハンドラを作成することになります。

という新しいクラスを作成する。 WebSocketHandlerという新しいクラスを作り @WebSocket:

import org.eclipse.jetty.websocket.api.annotations.WebSocket;

@WebSocket
public class WebSocketHandler {
    
}

が処理する各イベントは、アノテーションで定義される。 WebSocketHandlerアノテーションで定義されます。アノテーションは @OnWebSocketMessageアノテーションを使用して、バイナリまたはテキスト・イベントを受信するメソッドにタグを付けることができます。

デモンストレーションのために、受信したメッセージを送信者にエコーで返すエコー・サーバーを作成する。

以下のメソッドを追加する:

@OnWebSocketMessage
public void handleTextMessage(Session session, String message) throws IOException {
    System.out.println("New Text Message Received");
    session.getRemote().sendString(message);
}

@OnWebSocketMessage
public void handleBinaryMessage(Session session, byte[] buffer, int offset, int length) throws IOException {
    System.out.println("New Binary Message Received");
    session.getRemote().sendBytes(ByteBuffer.wrap(buffer));
}

メソッド・シグネチャは、メソッドがどのタイプのメッセージを扱うかを決定することに注意してください。詳しくは OnWebSocketMessage注釈ドキュメントを参照してください。

WebSocketハンドラの登録

を使用するには WebSocketHandlerを使うには登録が必要です。

Gradleが作成した Appクラスを開いてください。メソッドと getGreetingメソッドと mainメソッドの内容を削除します。

メイン・メソッドの内部で、以下を追加して WebSocketHandlerを登録します。 /socketパスに登録します:

@Override
public void registerWebSocketHandlers(WebSocketHandlerRegistry registry) {
    webSocket("/socket", WebSocketHandler.class);
}

アプリケーションをテストするクライアントを作成する

WebSocketサーバーをテストするためにクライアントを作成する必要があります。テキスト・メッセージとバイナリ・メッセージの両方を送信するテストが必要です。これはJavaScriptで実現できます。

フォルダを resourcesフォルダーの中に src/mainフォルダーの中にフォルダの中に resourcesフォルダーの中に staticフォルダを作成する。

以下を index.htmlフォルダ内に src/main/resources/staticフォルダーの中に追加する:

<html>
<head>
    <style>
        #messages {
            text-align: left;
            width: 50%;
            padding: 1em;
            border: 1px solid black;
        }
    </style>
    <title>Sample WebSocket Client</title>
</head>
<body>
<div class="container">
    <div id="messages" class="messages"></div>
    <div class="input-fields">
        <p>Type a message and hit send:</p>
        <input id="message"/>
        <button id="send">Send</button>

        <p>Select an image and hit send:</p>
        <input type="file" id="file" accept="image/*"/>

        <button id="sendImage">Send Image</button>
    </div>
</div>
</body>
<script>
    const messageWindow = document.getElementById("messages");

    const sendButton = document.getElementById("send");
    const messageInput = document.getElementById("message");

    const fileInput = document.getElementById("file");
    const sendImageButton = document.getElementById("sendImage");

    const socket = new WebSocket("ws://localhost:8080/socket");
    socket.binaryType = "arraybuffer";

    socket.onopen = function (event) {
        addMessageToWindow("Connected");
    };

    socket.onmessage = function (event) {
        if (event.data instanceof ArrayBuffer) {
            addMessageToWindow('Got Image:');
            addImageToWindow(event.data);
        } else {
            addMessageToWindow(`Got Message: ${event.data}`);
        }
    };

    sendButton.onclick = function (event) {
        sendMessage(messageInput.value);
        messageInput.value = "";
    };

    sendImageButton.onclick = function (event) {
        let file = fileInput.files[0];
        sendMessage(file);
        fileInput.value = null;
    };

    function sendMessage(message) {
        socket.send(message);
        addMessageToWindow("Sent Message: " + message);
    }

    function addMessageToWindow(message) {
        messageWindow.innerHTML += `<div>${message}</div>`
    }

    function addImageToWindow(image) {
        let url = URL.createObjectURL(new Blob([image]));
        messageWindow.innerHTML += `<img src="${url}"/>`
    }
</script>
</html>

ここで、Sparkを設定して、アプリケーションの実行時に index.htmlを探し、アプリケーションの実行時にサーバーを初期化するように Spark を設定する必要があります。また、サーバーが接続をリッスンするポートを定義することもできる。

mainクラスの Appクラスのメソッドの中に、以下を追加する。 webSocket:

staticFileLocation("static");
port(8080)
init();

アプリケーションの開始

これでWebSocketサーバーは完成です。アプリケーションのディレクトリ内で gradle runコマンドを使ってアプリケーションを起動します。

アプリケーションは以下からアクセスできます。 http://localhost:8080にアクセスしてください:

Sample JavaScript-enabled client for testing the WebSocket server.Connected

connected "メッセージは、JavaScriptクライアントが接続できたことを示す。

入力フィールドに入力して送信ボタンをクリックし、テキストメッセージを送信してみてください。また、画像をアップロードしてみてください。どちらの場合も、同じメッセージと画像がエコーバックされるはずです。

Sample JavaScript-enabled client showing a text and binary message echoed back.Connected Check

結論

このチュートリアルでは、バイナリーとテキストの両方のメッセージを受信できるWebSocketサーバーをSparkを使って作成する方法を学びました。このチュートリアルの完成したコードは リポジトリにあります。リポジトリにあります。

WebSocketを既存の スプリングアプリケーションに実装したいですか?もしかしたら Spring BootでWebSocketサーバーを作る?

フレームワークがない?問題ない!次回のチュートリアルでは、Java API for WebSocketsを使ってWebSocketサーバーを作成する方法を紹介します。

のエンドポイントとしてWebSocketを使用できることをご存知ですか? Nexmoコールコントロールオブジェクト?次の例を見てください。 Voice WebSocketを使ったブラウザへのストリーミングコール.

WebSocketsの面白い使い方を見たいですか?を見てみましょう。 nexmo-コミュニティ/dtmf-snakeレポジトリを見ると、デュアルトーンのマルチ周波数信号を使ってスネークゲームをすることができるコードを見ることができる。

シェア:

https://a.storyblok.com/f/270183/150x150/a3d03a85fd/placeholder.svg
Steve Crowヴォネージの卒業生

スティーブは自称数学者で、悪口の王様。グレイハウンド、曲がりくねったパズル、ヨーロッパのボードゲームをこよなく愛する。 非数学系の人には数学を、非Java系の人にはJavaの話をしていないときは、コーヒーを飲みながらコードをハックしている。