Play Frameworkはサンプルでチャットの例が一緒に入っているのだがActorを絡めたコードになっており、ビミョーによくわからなかった。ので、他のWebSocketのサンプルでしばしば見られる、送信したメッセージをただ送りなおす、いわゆる「エコー」をやってみることにした。
やったこと
Play Frameworkさわる - kagamihogeのblogで環境作って、初期状態のプロジェクトをそのまんま流用する。
まずクライアント側のapp/views/websocketindex.scala.htmlはこんな感じ。
<!DOCTYPE html> <html> <head> <script src="@routes.Assets.at("javascripts/jquery-2.0.2.min.js")" type="text/javascript"></script> <script type="text/javascript" charset="utf-8"> $(function() { var WS = window['MozWebSocket'] ? MozWebSocket : WebSocket; var socket = new WS("@routes.Application.echowebsocketmessage().webSocketURL(request)"); socket.onmessage = function(event) { var data = JSON.parse(event.data); $("#onReceive").text(data.text) } $("#onSend").click(function () { socket.send(JSON.stringify({text: $("#sendMessage").val()})); }); }) </script> </head> <body> <textarea id="sendMessage"></textarea> <div id="onSend">click send message.</div> <div id="onReceive">dummy</div> </body> </html>
@routes.Application.echowebsocketmessage〜てな感じでURLを書くことができ、実際にページにアクセスすると該当部分は下記のようになる。
var socket = new WS("ws://localhost:9000/echowebsocketmessage");
他はWebSocketのコードで、playとは直接の関係が無いので特に無し。
conf/routes に新しいURLマッピング書き加える。
# Home page GET / controllers.Application.index() GET /echowebsocketindex controllers.Application.echowebsocketindex() GET /echowebsocketmessage controllers.Application.echowebsocketmessage()
/echowebsocketindex でページ表示して、/echowebsocketmessage に対してWebSocketの送受信する。
package controllers; import org.codehaus.jackson.JsonNode; import org.codehaus.jackson.node.ObjectNode; import play.libs.F.Callback; import play.libs.Json; import play.mvc.Controller; import play.mvc.Result; import play.mvc.WebSocket; import views.html.index; import views.html.websocketindex; public class Application extends Controller { public static Result index() { System.out.println("root"); return ok(index.render("Your new application is ready.")); } public static Result echowebsocketindex() { return ok(websocketindex.render()); } public static WebSocket<JsonNode> echowebsocketmessage() { return new WebSocket<JsonNode>() { public void onReady(WebSocket.In<JsonNode> in, WebSocket.Out<JsonNode> out){ try { in.onMessage(new EchoCallback(out)); } catch (Exception ex) { ex.printStackTrace(); } } }; } public static class EchoCallback implements Callback<JsonNode> { private WebSocket.Out<JsonNode> out; public EchoCallback(WebSocket.Out<JsonNode> out) { this.out = out; } @Override public void invoke(JsonNode event) throws Throwable { ObjectNode echo = Json.newObject(); echo.put("text", "[echo]" + event.get("text").asText()); out.write(echo); } } }
こんくらい最小限度のコードにしてしまえば、そんなにややこしいもんでなかった。