Documentation

You are viewing the documentation for the 2.3.x release series. The latest stable release series is 2.4.x.

§WebSocket

WebSockets are sockets that can be used from a web browser based on a protocol that allows two way full duplex communication. The client can send messages and the server can receive messages at any time, as long as there is an active WebSocket connection between the server and the client.

Modern HTML5 compliant web browsers natively support WebSockets via a JavaScript WebSocket API. However WebSockets are not limited in just being used by WebBrowsers, there are many WebSocket client libraries available, allowing for example servers to talk to each other, and also native mobile apps to use WebSockets. Using WebSockets in these contexts has the advantage of being able to reuse the existing TCP port that a Play server uses.

§WebSocket を使う

Until now, we’ve been writing methods that return Result to handle standard HTTP requests. WebSockets are quite different and can’t be handled via standard Play actions.

Play provides two different built in mechanisms for handling WebSockets. The first is using actors, the second is using simple callbacks. Both of these mechanisms can be accessed using the builders provided on WebSocket.

§Handling WebSockets with actors

To handle a WebSocket with an actor, we need to give Play a akka.actor.Props object that describes the actor that Play should create when it receives the WebSocket connection. Play will give us an akka.actor.ActorRef to send upstream messages to, so we can use that to help create the Props object:

Java 8
import play.mvc.WebSocket;
public static WebSocket<String> socket() {
    return WebSocket.withActor(MyWebSocketActor::props);
}
Java
import akka.actor.*;
import play.libs.F.*;
import play.mvc.WebSocket;
public static WebSocket<String> socket() {
    return WebSocket.withActor(new Function<ActorRef, Props>() {
        public Props apply(ActorRef out) throws Throwable {
            return MyWebSocketActor.props(out);
        }
    });
}

The actor that we’re sending to here in this case looks like this:

import akka.actor.*;

public class MyWebSocketActor extends UntypedActor {

    public static Props props(ActorRef out) {
        return Props.create(MyWebSocketActor.class, out);
    }

    private final ActorRef out;

    public MyWebSocketActor(ActorRef out) {
        this.out = out;
    }

    public void onReceive(Object message) throws Exception {
        if (message instanceof String) {
            out.tell("I received your message: " + message, self());
        }
    }
}

Any messages received from the client will be sent to the actor, and any messages sent to the actor supplied by Play will be sent to the client. The actor above simply sends every message received from the client back with I received your message: prepended to it.

§Detecting when a WebSocket has closed

When the WebSocket has closed, Play will automatically stop the actor. This means you can handle this situation by implementing the actors postStop method, to clean up any resources the WebSocket might have consumed. For example:

public void postStop() throws Exception {
    someResource.close();
}

§Closing a WebSocket

Play will automatically close the WebSocket when your actor that handles the WebSocket terminates. So, to close the WebSocket, send a PoisonPill to your own actor:

self().tell(PoisonPill.getInstance(), self());

§Rejecting a WebSocket

Sometimes you may wish to reject a WebSocket request, for example, if the user must be authenticated to connect to the WebSocket, or if the WebSocket is associated with some resource, whose id is passed in the path, but no resource with that id exists. Play provides a reject WebSocket builder for this purpose:

Java 8
public static WebSocket<String> socket() {
    if (session().get("user") != null) {
        return WebSocket.withActor(MyWebSocketActor::props);
    } else {
        return WebSocket.reject(forbidden());
    }
}
Java
public static WebSocket<String> socket() {
    if (session().get("user") != null) {
        return WebSocket.withActor(new Function<ActorRef, Props>() {
            public Props apply(ActorRef out) throws Throwable {
                return MyWebSocketActor.props(out);
            }
        });
    } else {
        return WebSocket.reject(forbidden());
    }
}

§Accepting a WebSocket asynchronously

You may need to do some asynchronous processing before you are ready to create an actor or reject the WebSocket, if that’s the case, you can simply return Promise<WebSocket<A>> instead of WebSocket<A>.

§Handling different types of messages

So far we have only seen handling String frames. Play also has built in handlers for byte[] frames, and JSONNode messages parsed from String frames. You can pass these as the type parameters to the WebSocket creation method, for example:

Java 8
public static WebSocket<JsonNode> socket() {
    return WebSocket.withActor(MyWebSocketActor::props);
}
Java
public static WebSocket<JsonNode> socket() {
    return WebSocket.withActor(new Function<ActorRef, Props>() {
        public Props apply(ActorRef out) throws Throwable {
            return MyWebSocketActor.props(out);
        }
    });
}

§Handling WebSockets using callbacks

If you don’t want to use actors to handle a WebSocket, you can also handle it using simple callbacks.

WebSocket を扱うためには、Result の代わりに WebSocket を返す必要があります。

Java 8
public static WebSocket<String> socket() {
    return WebSocket.whenReady((in, out) -> {
        // For each event received on the socket,
        in.onMessage(System.out::println);

        // When the socket is closed.
        in.onClose(() -> System.out.println("Disconnected"));

        // Send a single 'Hello!' message
        out.write("Hello!");
    });
}
Java
public static WebSocket<String> socket() {
    return new WebSocket<String>() {

        // Called when the Websocket Handshake is done.
        public void onReady(WebSocket.In<String> in, WebSocket.Out<String> out) {

            // For each event received on the socket,
            in.onMessage(new Callback<String>() {
                public void invoke(String event) {

                    // Log events to the console
                    System.out.println(event);

                }
            });

            // When the socket is closed.
            in.onClose(new Callback0() {
                public void invoke() {

                    System.out.println("Disconnected");

                }
            });

            // Send a single 'Hello!' message
            out.write("Hello!");

        }

    };
}

WebSocketは リクエストヘッダ (WebSocket 接続を初期化するための HTTP リクエストに付加されていたもの) を参照することができるため、標準的なヘッダの内容やセッションデータを受け取ることができます。しかし、リクエストボディや HTTP レスポンスへは一切アクセスできません。

WebSocket の準備が終わると、inout という二つのチャンネルが得られます。

この例では、受け取ったメッセージをコンソールへ出力しつつ、単一の Hello! というメッセージを送信しています。

Tip: WebSocket コントローラは http://websocket.org/echo.html でテストすることができます。テストを行うためには、location として ws://localhost:9000 を指定してください。

次は、入力データを全て捨てつつ、**Hello!** メッセージを送信した後すぐにソケットを閉じる例を書いてみましょう。

Java 8
public static WebSocket<String> socket() {
    return WebSocket.whenReady((in, out) -> {
        out.write("Hello!");
        out.close();
    });
}
Java
public static WebSocket<String> socket() {
    return new WebSocket<String>() {

        public void onReady(WebSocket.In<String> in, WebSocket.Out<String> out) {
            out.write("Hello!");
            out.close();
        }

    };
}

次ページ: テンプレートエンジン


このドキュメントの翻訳は Play チームによってメンテナンスされているものではありません。 間違いを見つけた場合、このページのソースコードを ここ で確認することができます。 ドキュメントガイドライン を読んで、お気軽にプルリクエストを送ってください。