PlayFramework 2.0 Javaと WebSocketでつくる リアルタイムMVC Webアプリケーション

  • 16,331 views
Uploaded on

JavaOne Tokyoの時の資料です。http://www.oracle.co.jp/javaone/2012/timetable/index.html …

JavaOne Tokyoの時の資料です。http://www.oracle.co.jp/javaone/2012/timetable/index.html
Blogにて補足説明があったりします。
http://blog.greative.jp/

More in: Technology
  • Full Name Full Name Comment goes here.
    Are you sure you want to
    Your message goes here
  • やりたいことの資料
    Are you sure you want to
    Your message goes here
No Downloads

Views

Total Views
16,331
On Slideshare
0
From Embeds
0
Number of Embeds
8

Actions

Shares
Downloads
97
Comments
1
Likes
44

Embeds 0

No embeds

Report content

Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel
    No notes for slide

Transcript

  • 1. PlayFramework 2.0 Javaと WebSocketでつくる リアルタイムMVC Webアプリケーション 原 一浩 @kara_d
  • 2. 原 一浩 @kara_d NetBeans / SublimeText 2
  • 3. 何してる人? Greative is Great Creative デザイントレンド、統計、システム
  • 4. 本日のセッション内容https://github.com/karad/PlayWebSocketReversi 4
  • 5. 本日のセッション内容 サンプルダウンロードURLhttps://github.com/karad/PlayWebSocketReversi 5
  • 6. 目次 ➡ PlayFrameworkとWebSocketの概要 ➡ WebSocketアプリ制作の概要 • Play 1.2.x • Play 2.0 ➡ サンプル:Reversiの実装とデモ ➡ まとめhttps://github.com/karad/PlayWebSocketReversi 6
  • 7. Play Frameworkとはhttps://github.com/karad/PlayWebSocketReversi 7
  • 8. PlayFrameworkとは ➡ オープンソース(zenexity製) ➡ non Servlet、non XML ➡ ステートレス ➡ MVCフレームワーク ➡ ホットデプロイ ➡ ノンブロッキング IO ➡ HTTPマッピング ➡ テスト環境 ➡ シェルサポートhttps://github.com/karad/PlayWebSocketReversi 8
  • 9. PlayFramework 1.2.xまで ➡ テンプレートはGroovy ➡ フルスタック ➡ JPA拡張によるORM ➡ Javaベース ➡ Pythonによるシェル ➡ Scalaモジュールhttps://github.com/karad/PlayWebSocketReversi 9
  • 10. PlayFramework 2.0 ➡ テンプレートはScala ➡ モジュール型 ➡ 一部ORM選択可能 • JavaはEBean • ScalaはAnormやScalaQuery ➡ Scalaベース ➡ SBTによるビルドシステム • 従来のplayコマンドに相当 ➡ Akkaによる非同期処理 ➡ Java/Scalaサポートhttps://github.com/karad/PlayWebSocketReversi 10
  • 11. PlayFramework 2.0 more... ➡ ドキュメントが整備 ➡ サンプルが豊富 ➡ CoffeeScriptサポート ➡ LESSサポート ➡ Google Clojure Compilerサポート ➡ ヘルパー機能https://github.com/karad/PlayWebSocketReversi 11
  • 12. どちらを使うべきか? ➡ 安心の1.2.x • 大量のサードパーティモジュール • バグフィックスが進んでいる • 業務で使用実績 ➡ 挑戦の2.0 • モジュールは、あまりない • 出たばかりで、まだバグ多い • 業務実績などもこれから アプリの互換性は、ほぼありませんhttps://github.com/karad/PlayWebSocketReversi 12
  • 13. ニュース ➡ 最近本家のMLがごたごたしてた ➡ 今後1.2系はメンテナンスモードに • つまり1.3は出ない • 1.2.5は月末に出るっぽい ➡ 2.0は、JavaとScala両方を今後サポートしていく ➡ 1.2系をforkする人も? ➡ 1.2系と2.0ではサイトを分ける ➡ 今後はプロジェクトのテンプレートはgiter8でhttps://github.com/karad/PlayWebSocketReversi 13
  • 14. Play 2.0 Overviewhttps://github.com/karad/PlayWebSocketReversi 14
  • 15. Play 2.0フォルダ ➡ app ➡ logs • controllers ➡ project • models ➡ public • views ➡ conf • images • javascripts • application.conf • stylesheets • routes ➡ target • IDEを使う人には大事https://github.com/karad/PlayWebSocketReversi 15
  • 16. Play2.0のサイト構築、基本の流れ(Java) ➡ モデルの構築 • テスト:Unit Test ➡ コントローラーの構築 • テスト:Functional Test ➡ ビューの構築 • テスト:Selenuimベースのfluentleniumhttps://github.com/karad/PlayWebSocketReversi 16
  • 17. モデル ➡ ORMとしてEBeanを採用 ➡ findやバリデーション(Constraints.*)に対応 @Entity public  class  User  extends  Model{        @Id        public  Long  id;                @Constraints.Required        public  String  name; }https://github.com/karad/PlayWebSocketReversi 17
  • 18. コントローラ ➡ 基本、Resultを返す public  class  Application  extends  Controller  {    public  static  Result  index()  {        return  ok(index.render());    } }https://github.com/karad/PlayWebSocketReversi 18
  • 19. レイアウト ➡ レイアウトとビューの区別はない ➡ 呼び出しによる入れ子構造 @(title:  Html,  nav:  String  =  "")(content:  Html) <!DOCTYPE  html> <html>    <head><title>@title</title></head>    <body>        <h1>@title</h1>                @content    </body> </html> main.scala.htmlhttps://github.com/karad/PlayWebSocketReversi 19
  • 20. ビューテンプレート ➡ main.scala.htmlを呼び出す ➡ 引数と内容(content) @main(Html("Samples"))  {    <p>Hello!</p> } index.scala.htmlhttps://github.com/karad/PlayWebSocketReversi 20
  • 21. リアルタイム通信サーバの これまでhttps://github.com/karad/PlayWebSocketReversi 21
  • 22. Flashでのリアルタイム通信 ➡ Adobe Flash Communication Server ➡ Adobe Flash Media Server Real Time Messaging Protocol(RTMP) ➡ Red5 • http://www.red5.org/ • Javaで作られている • オープンソースhttps://github.com/karad/PlayWebSocketReversi 22
  • 23. WebSocketとはhttps://github.com/karad/PlayWebSocketReversi 23
  • 24. WebSocketは、W3CとIETFが策定 ➡ 元々はHTML5の一部 ➡ 双方向の通信技術 ➡ AjaxやCommetよりも自然に双方向通信 ➡ コネクション後、専用のプロトコルで通信 • ハンドシェイク • ws:もしくはwss:※ ➡ 最終仕様は、RFC6455。対応は下記 • IE 10 Platform Preview 5※ • Firefox 11 • Google Chrome 16 • Safari 最新※https://github.com/karad/PlayWebSocketReversi 24
  • 25. WebSocket未対応ブラウザへhttps://github.com/karad/PlayWebSocketReversi 25
  • 26. web-socket-js ➡ https://github.com/gimite/web-socket-js • Google Chrome 4 or later, Firefox 6 or later • Firefox 3 to 5, Internet Explorer 8, 9 + Flash Player 10 or laterhttps://github.com/karad/PlayWebSocketReversi 26
  • 27. PlayFrameworkでの利用 ➡ ダウンロードしたら、 • public/javascripts/ に「swfobject.js」「web_socket.js」 • public/swfs/ に「WebSocketMain.swf」 • 配置し、JavaScript側で呼び出せるようにしたら終わりhttps://github.com/karad/PlayWebSocketReversi 27
  • 28. JavaScriptでのWebSocketの接続方法 WEB_SOCKET_SWF_LOCATION  =  "SWFを配置したパス"; WEB_SOCKET_DEBUG  =  false; var  socket; socket  =  new  WebSocket( @routes.Application.game().webSocketURL(request)) ➡ Flashを介している点が異なる ➡ こうすることで未対応ブラウザでも動作可能https://github.com/karad/PlayWebSocketReversi 28
  • 29. JavaScriptのWebSocketのAPI ➡ socket = WebSocket(url, protocols) ➡ socket.send() ➡ socket.close() イベントハンドラ ➡ socket.onmessage ➡ socket.onopen ➡ socket.onerror ➡ socket.onclosehttps://github.com/karad/PlayWebSocketReversi 29
  • 30. WebSocket通信の確認にはChromeが便利https://github.com/karad/PlayWebSocketReversi 30
  • 31. PlayFrameworkと WebSockethttps://github.com/karad/PlayWebSocketReversi 31
  • 32. Play1.2.3 ➡ hybi-00 • Chrome 14までサポート Play1.2.4 ➡ hybi-10 • バージョン8 • Chrome 16までサポート パッチ(Lighthouse 1240 patch) ➡ RFC6455 • 最新版に対応https://github.com/karad/PlayWebSocketReversi 32
  • 33. パッチ(Lighthouse 1240 patch)の当て方 ➡ 該当のパッチを当てる • https://github.com/playframework/play/pull/438 を参照 • framework/src/play/server/PlayHandler.java を修正 ➡ 修正後、antタスクを実行 $  ~/play-­‐1.2.4/framework $  ant   Buildfile:  /Users/harakazuhiro/play-­‐1.2.4/framework/ build.xml ..... BUILD  SUCCESSFUL Total  time:  22  secondshttps://github.com/karad/PlayWebSocketReversi 33
  • 34. パッチが当たったリビルド版 ➡ バージョン表記が「play! 1.2.x-localbuild」に $  play  run                                                                                             ~                _                        _   ~    _  __  |  |  __  _  _    _|  | ~  |  _  |  |/  _  |  ||  |_| ~  |    __/|_|____|__  (_) ~  |_|                        |__/       ~ ~  play!  1.2.x-­‐localbuild,  http://www.playframework.orghttps://github.com/karad/PlayWebSocketReversi 34
  • 35. Play以外の対応、ご参考まで •https://github.com/karad/PlayWebSocketReversi 35
  • 36. WebSocketをフレームワークに載せる意味 ➡ Webアプリケーションとのシームレスな統合 ➡ WebSocketをコントローラーにして設計が容易に ➡ 認証系、データ管理系の実装が楽になる WebSocketアプリケーションとポート ➡ 基本的には、Playが動いているポートになる ➡ Apacheのmod_proxyを経由させている場合は注意https://github.com/karad/PlayWebSocketReversi 36
  • 37. Play 1.2.4のWebSockethttps://github.com/karad/PlayWebSocketReversi 37
  • 38. WebSocketController ➡ Staticによるアクション ➡ ルーティングが可能 ➡ InboundとOutboundの2チャンネル ➡ request、params、validation、session ➡ disconnect()で通信の切断 ➡ awaitメソッドで処理の待機 ➡ ビューで、wsプロトコルのURLに • Routesでプロトコルの指定が必要https://github.com/karad/PlayWebSocketReversi 38
  • 39. InboundとOutbound ➡ Inbound • WebSocketの受信 • WebSocketのソケットオープン中、 inbound.isOpen()がtrue • inbound.nextEvent()にて、イベントを取得 ➡ Outbound • WebSocketの送信 • outbound.send(String string)にて送信 • sendメソッドには、opcodeを指定可能 - outbound.send(byte opcode, byte[] data);https://github.com/karad/PlayWebSocketReversi 39
  • 40. Outboundあれこれ ➡ テキストフレームは、通常下記みたいな利用をするが、 • outbound.send("quit:ok"); ➡ JSONでも送信が可能。sendJsonを使用する • outbound.sendJson(Object); ➡ 生データ • send( byte opcode, byte[] data)https://github.com/karad/PlayWebSocketReversi 40
  • 41. テキストフレームのやりとり ➡ 受信 • play.mvc.Http.WebSocketEvent.TextFrameから Matcherを使ってtextDataを取り出す for(String  textData:  TextFrame.match(e._1))  {        ...処理... } ➡ 送信 • outbound.send(String string)を使って送信https://github.com/karad/PlayWebSocketReversi 41
  • 42. PlayFramework 1.2.4でのサンプルhttps://github.com/karad/PlayWebSocketReversi 42
  • 43. WebSocket:サーバーとクライアント PlayFramework DB WebSocketハンドシェイク 1 Webサイト WebSocketソケット通信 WebSocket Controller 5 Outboundアプリごとにイベント Model WebSocket Inbound 2デザインが Event Event必要 Join TextFrame Message SocketClose Leave BinaryFrame 4 3https://github.com/karad/PlayWebSocketReversi 43
  • 44. 全体構成 ➡ クライアント • プロパティを「:」でつないだメッセージ • コマンド : ユーザー : メッセージ • message : name : text ➡ サーバー • WebSocketControllerクラスを継承したChatRoomSocket • ChatRoomSocketには、joinメソッドのみがある • ChatRoomモデル内でチャットのイベントを設定 • inbound.isOpen()の限りループ - Either<WebSocketEvent,ChatRoom.Event> eが評価されない限りは停止https://github.com/karad/PlayWebSocketReversi 44
  • 45. • 各種イベントにマッチするものがあれば、各処理を実行 - WebSocketのイベントが、TextFrameかつTextFrameがquit - WebSocketのイベントが、TextFrame - Chatroom内のイベントが、ChatRoom.Joinクラス - Chatroom内のイベントが、ChatRoom.Messageクラス - Chatroom内のイベントが、ChatRoom.Leaveクラス - WebSocketのイベントが、SocketClosed public  static  void  join(String  user)  {        while(inbound.isOpen())  {                Either<WebSocketEvent,ChatRoom.Event>  e  =   ここで停止                        await(Promise.waitEither(                                inbound.nextEvent(),                                  roomMessagesStream.nextEvent()));                ...各種処理...        } }https://github.com/karad/PlayWebSocketReversi 45
  • 46. ChatModelは、イベント管理モデル ➡ 内部にEventクラスというabstractなクラスを用意 ➡ Eventクラスを継承した各種イベントクラス • Joinクラス • Leaveクラス • Messageクラス ChatRoomSocketでのイベント判定 ➡ ChatRoom.Eventクラスをパターンマッチで分岐 • ClassOf(ChatRoom.Join.class).match(e._2) • ClassOf(ChatRoom.Message.class).match(e._2) • ClassOf(ChatRoom.Leave.class).match(e._2)https://github.com/karad/PlayWebSocketReversi 46
  • 47. Play 2.0のWebSockethttps://github.com/karad/PlayWebSocketReversi 47
  • 48. WebSocket:サーバーとクライアント DB PlayFramework WebSocketハンドシェイク 1 onReady Model(In) Webサイト WebSocketソケット通信 WebSocket.out Outアプリごと 3 Akkaにイベント Event onReceiveデザインが必要 Join In WebSocket.in 2 Message onMessage Quit 4 onClosehttps://github.com/karad/PlayWebSocketReversi 48
  • 49. WebSocket用コントローラ ➡ Staticによるアクション ➡ ルーティングが可能 ➡ WebSocketオブジェクトの入出力 • InとOutの2チャンネル ➡ ほとんどの処理はモデルに移動 ➡ onReady()イベントを定義https://github.com/karad/PlayWebSocketReversi 49
  • 50. WebSocket対応のコントローラー public  static  WebSocket<JsonNode>  game(        final  String  username        )  {        return  new  WebSocket<JsonNode>()  {                public  void  onReady(WebSocket.In<JsonNode>  in,   WebSocket.Out<JsonNode>  out){                        try  {                                  Reversi.join(username,  in,  out);                        }  catch  (Exception  ex)  {                                ex.printStackTrace();                        }                }        }; }https://github.com/karad/PlayWebSocketReversi 50
  • 51. WebSocket用モデル ➡ 専用のクラス • UntypedActor ➡ Akkaベースの非同期プログラミング ➡ 同期処理は、Awaitメソッド ➡ In.onMessageと、In.onClose ➡ onReceive()イベントを定義 ➡ Out.write()で送信 ➡ メンバーとチャンネルhttps://github.com/karad/PlayWebSocketReversi 51
  • 52. WebSocket対応のモデルの一部 public  void  onReceive(Object  message)          throws  Exception  {        if  (message  instanceof  Join)  {                //  Received  a  Join  message        }  else  if  (message  instanceof  Message)  {                Message  talk  =  (Message)  message;                notifyAll(                        "talk",  talk.username,  talk.text,                          talk.x,  talk.y,  talk.uuid);        }  else  if  (message  instanceof  Quit)  {                //  Received  a  Quit  message        } }https://github.com/karad/PlayWebSocketReversi 52
  • 53. AkkaとWebSocketの関係 ➡ WebSocket.In WebSocket.In • メッセージ受け取り時 tell • onMessage(Callback<A> callback) - event ActorRef ➡ Akkaのアクター • イベントの監視、非同期処理 write • onReceive(Object message) ➡ WebSocket.Out WebSocket.Out • 通信の書き出し • write(A frame)https://github.com/karad/PlayWebSocketReversi 53
  • 54. サンプル:Reversihttps://github.com/karad/PlayWebSocketReversi 54
  • 55. デモ ➡ https://github.com/karad/PlayWebSocketReversihttps://github.com/karad/PlayWebSocketReversi 55
  • 56. Reversi作成の手順 ➡ Playアプリケーションの作成 ➡ メッセージフォーマットの設計 ➡ イベントモデルの設計 ➡ コントローラ、モデルの作成 ➡ ルーティングの作成 ➡ ビューの作成 【参考】作業ステップをつけています Restful Make Format Event Scheme Model and Controller Routing Fronthttps://github.com/karad/PlayWebSocketReversi 56
  • 57. Playアプリケーションの作成(1) ➡ システム企画 • ユーザーは2人(BlackとWhite)の選択 • 盤面をロールオーバーすると相手にも伝わる • 盤面をクリックすると自分の色に変わる • 駒はどこでも配置可能 画面遷移 WebSocket Login Game WS トップページ ゲーム画面 Restful Make Format Event Scheme Model and Controller Routing Fronthttps://github.com/karad/PlayWebSocketReversi 57
  • 58. Playアプリケーションの作成(2) ➡ トップページ Login • http://URL/ ➡ ゲーム画面 • http://URL/reversi/ Game ➡ WebSocket • ws://URL/reversi/game?username=hoge WS Restful Make Format Event Scheme Model and Controller Routing Fronthttps://github.com/karad/PlayWebSocketReversi 58
  • 59. Playアプリケーションの作成(3) ➡ コントローラ • app/controllers/Application.java - HTTPリクエストを受けるところ ➡ モデル • app/models/Reversi.java - WebSocket周りのイベント処理を記述 ➡ ビュー • app/views/index.scala.html • app/views/main.scala.html • app/views/reversi.scala.html Restful Make Format Event Scheme Model and Controller Routing Fronthttps://github.com/karad/PlayWebSocketReversi 59
  • 60. メッセージのフォーマット(JSON)を決める ➡ kind • join、talk、quitの各種フラグ ➡ user • ユーザー名(black or white) ➡ x、y ➡ uuid • 各升目のユニークid ➡ message • thinkOver、thinkOut、black、whiteの各メッセージ Restful Make Format Event Scheme Model and Controller Routing Fronthttps://github.com/karad/PlayWebSocketReversi 60
  • 61. イベントの種類を決める ➡ 各イベントごとにクラスを作成 ➡ public static class Join(username、channel) … 参加 ➡ public static class Message(username、text、x、y、uuid) … 送信 ➡ public static class Quit(username) … 終了 Restful Make Format Event Scheme Model and Controller Routing Fronthttps://github.com/karad/PlayWebSocketReversi 61
  • 62. コントローラの作成(1):Application.java ➡ 各種メソッドを実装 ➡ public static Result index() … トップページ • index.scala.html を表示 ➡ public static Result reversi(username) … ゲーム画面 • ゲーム画面用アクション • ユーザー名を取得し、ゲーム画面 reversi.scala.html を表示 Restful Make Format Event Scheme Model and Controller Routing Fronthttps://github.com/karad/PlayWebSocketReversi 62
  • 63. コントローラの作成(2):Application.java ➡ public static WebSocket<JsonNode> game(final String username) … WebSocket • WebSocket用アクション • 初接続時は、ユーザー名をメンバーとしてJoinメソッドを呼び出し • 2回目以降は、JsonFrameをInboundとして処理 Restful Make Format Event Scheme Model and Controller Routing Fronthttps://github.com/karad/PlayWebSocketReversi 63
  • 64. モデルの作成(1):Reversi.javaの構成 ➡ static ActorRef game … アクター ➡ Map<String, WebSocket.Out<JsonNode>> members … メンバー一覧 ➡ public static void join(username, in, out) … 参加メソッド ➡ public void onReceive(message) … 受信 ➡ public void notifyAll(kind, user, text, x, y, uuid) … 全員に通知 Restful Make Format Event Scheme Model and Controller Routing Fronthttps://github.com/karad/PlayWebSocketReversi 64
  • 65. モデルの作成(2) ➡ イベント用のインナークラス用意 • Join public  static  class  Join  { • Message        final  String  username; • Quit        final  WebSocket.Out<JsonNode>  channel;        public  Join(                String  username,                  WebSocket.Out<JsonNode>  channel        )  {                this.username  =  username;                this.channel  =  channel;        } } Restful Make Format Event Scheme Model and Controller Routing Fronthttps://github.com/karad/PlayWebSocketReversi 65
  • 66. モデルの作成(3) ➡ static ActorRef game … アクター static  ActorRef  game  =      Akka.system().actorOf(new  Props(Reversi.class)); ➡ Map<String, WebSocket.Out<JsonNode>> members … メンバー一覧 Map<String,  WebSocket.Out<JsonNode>>  members  =      new  HashMap<String,  WebSocket.Out<JsonNode>>(); Restful Make Format Event Scheme Model and Controller Routing Fronthttps://github.com/karad/PlayWebSocketReversi 66
  • 67. モデルの作成(4) ➡ public static void join(username, in, out) … 参加メソッド • 接続を行う最初のみ呼び出される • ユーザー名と、Inbound、Outboundを引数 • Joinクラスのインスタンスをメッセージとしてgameに送信 • InboundのonMessageハンドラを設定 - Messageクラスのインスタンスを送信 • InboundのonCloseハンドラ時を設定 - Quitクラスのインスタンスを送信 Restful Make Format Event Scheme Model and Controller Routing Fronthttps://github.com/karad/PlayWebSocketReversi 67
  • 68. モデルの作成(5) ➡ public void onReceive(message) … 受信 • 送信されてきたメッセージのクラスによって処理を振分け • Joinクラスだった場合 - メンバーに追加 • Messageクラスだった場合 - Outboundにメッセージを送信 • Quitクラスだった場合 - メンバーからusernameを削除 - 退出のメッセージ Restful Make Format Event Scheme Model and Controller Routing Fronthttps://github.com/karad/PlayWebSocketReversi 68
  • 69. onReceiveメソッドの抜粋 public  void  onReceive(Object  message)          throws  Exception  {        if  (message  instanceof  Join)  {                //  Received  a  Join  message        }  else  if  (message  instanceof  Message)  {                Message  talk  =  (Message)  message;                notifyAll(                        "talk",  talk.username,  talk.text,                          talk.x,  talk.y,  talk.uuid);        }  else  if  (message  instanceof  Quit)  {                //  Received  a  Quit  message        } }https://github.com/karad/PlayWebSocketReversi 69
  • 70. モデルの作成(6) ➡ public void notifyAll(kind, user, text, x, y, uuid) … 全員に通知 • 各プロパティをJSON形式で格納 • JSONをメンバー全員に送信 Restful Make Format Event Scheme Model and Controller Routing Fronthttps://github.com/karad/PlayWebSocketReversi 70
  • 71. ルーティングの設定 ➡ ルーティングは、conf/routesファイルを編集 GET          /                            controllers.Application.index() GET          /reversi              controllers.Application.reversi (username:  String  ?=  null) GET          /reversi/game    controllers.Application.game (username) Restful Make Format Event Scheme Model and Controller Routing Fronthttps://github.com/karad/PlayWebSocketReversi 71
  • 72. ビュー周りの設定(1):ビューですること ➡ レイアウトの用意 ➡ ログイン画面を用意 ➡ ゲーム画面を用意 ➡ ゲーム用のクラスを用意 ➡ 通信用のJavaScriptを用意 ➡ マウスイベント用のJavaScriptを用意 Restful Make Format Event Scheme Model and Controller Routing Fronthttps://github.com/karad/PlayWebSocketReversi 72
  • 73. ビュー周りの設定(2) ➡ レイアウトの用意 Restful Make Format Event Scheme Model and Controller Routing Fronthttps://github.com/karad/PlayWebSocketReversi 73
  • 74. ビュー周りの設定(3) ➡ ログイン画面を用意 Restful Make Format Event Scheme Model and Controller Routing Fronthttps://github.com/karad/PlayWebSocketReversi 74
  • 75. ビュー周りの設定(4) ➡ ゲーム画面を用意 Restful Make Format Event Scheme Model and Controller Routing Fronthttps://github.com/karad/PlayWebSocketReversi 75
  • 76. ビュー周りの設定(5) ➡ ゲーム用のクラスを用意 .white .black .thinkOut .thinkOver Restful Make Format Event Scheme Model and Controller Routing Fronthttps://github.com/karad/PlayWebSocketReversi 76
  • 77. ビュー周りの設定(6) ➡ 通信用のJavaScriptを用意 • WebSocketに接続 • メッセージを受信したら、内容に応じて処理 • kindがtalkなら、駒の配置もしくはロールオーバーの表示 var  chatSocket  =  new  WS("WEBSOCKET") var  receiveEvent  =  function(event)  {    var  data  =  JSON.parse(event.data);    //  各種処理 } chatSocket.onmessage  =  receiveEvent; Restful Make Format Event Scheme Model and Controller Routing Fronthttps://github.com/karad/PlayWebSocketReversi 77
  • 78. ビュー周りの設定(7) ➡ マウスイベント用のJavaScriptを用意 • mouseover時 - textに"thinkOver" - x座標、y座標、uuidに $(this).attr(id) • mouseout時 - textに"thinkOut"、その他は同じ • click時 - textに"ユーザー名"、その他は同じ ➡ WebSocketとして送信 • chatSocket.send(JSON.stringify(オブジェクト)); Restful Make Format Event Scheme Model and Controller Routing Fronthttps://github.com/karad/PlayWebSocketReversi 78
  • 79. WebSocket通信中のJSON ➡ コマンドラインにて確認可能 org.codehaus.jackson.node.ObjectNode@8bfaf9f[    _children={kind="talk",  user="black",  x=5,  y=4,  uuid="4_5",  message="thinkOut",  members=["black"]}     _nodeFactory=org.codehaus.jackson.node.JsonNodeFactory @fbf00a9 ]; Restful Make Format Event Scheme Model and Controller Routing Fronthttps://github.com/karad/PlayWebSocketReversi 79
  • 80. F.javaの話https://github.com/karad/PlayWebSocketReversi 80
  • 81. F.java:Play 1.2.x ➡ WebSocket周りを見ていくと、必ず当たる壁 ➡ Javaで関数言語的な使い方をサポートするライブラリ • Either - E2、E3、E4、E5まである - Haskel由来? • ArchivedEventStream - イベントのキューとして扱う仕組み • Matcher - パターンマッチ用 • Promise - 非同期処理https://github.com/karad/PlayWebSocketReversi 81
  • 82. パターンマッチFor文:Play 1.2.x for(String  a:  TextFrame.match(e._1))  {        ...処理... } for(String  a:  TextFrame.and(Equals("quit")) .match(e._1))  {        ...処理... } 明示的なキャストが存在しないので、すべてがタイプセーフであり、コンパイラ によって型チェックが行われます。https://github.com/karad/PlayWebSocketReversi 82
  • 83. F.javaのMatcher周り:Play 1.2.x ➡ String • 文字列でマッチ ➡ ClassOf • クラスでマッチ ➡ StartsWith • プレフィックスでマッチ ➡ Re • 正規表現パターンでマッチ ➡ Equals • 等価な文字列でマッチhttps://github.com/karad/PlayWebSocketReversi 83
  • 84. WebSocketEvent周りのMatcher ➡ SocketClosed.match() • WebSocketCloseかどうかでマッチ ➡ TextFrame.match() • WebSocketフレームがバイナリでなく、なおかつtextDataでマッチ ➡ BinaryFrame.match() • WebSocketフレームがバイナリで、binaryDataでマッチhttps://github.com/karad/PlayWebSocketReversi 84
  • 85. F.java:Play 2.0 ➡ Javaで関数言語的な使い方をサポートするライブラリ • Either - E2相当のみになった • Callback - Callback0、Callback1、Callback2、Callback3まである - コールバックを実現する • ArchivedEventStream - Akkaが肩代わり • Matcher - なくなった • Promise - 独自実装、Akkaとの連携もありhttps://github.com/karad/PlayWebSocketReversi 85
  • 86. F.javaの利用について ➡ F.javaはバージョンごとに変化が激しい ➡ 現状は読むのみに ➡ WebSocket周りでは必須https://github.com/karad/PlayWebSocketReversi 86
  • 87. まとめhttps://github.com/karad/PlayWebSocketReversi 87
  • 88. WebSocketアプリの設計・構築手順 ➡ Playアプリケーションの作成 Restful ➡ メッセージフォーマットの設計 Make Format ➡ イベントモデルの設計 Event Scheme ➡ コントローラ、モデルの作成 Model and Controller ➡ ルーティングの作成 Routing ➡ ビューの作成 Front クラスベースハンドラのイベント駆動プログラム関数型風味 WebSocketは、チャットを作るための機能ではないhttps://github.com/karad/PlayWebSocketReversi 88
  • 89. WebSocketはどこで役に立つのか? ➡ ログイン以降は、ユーザーによる細かな操作が続く ➡ Ajaxで行ってきた部分の上位バージョンとして ➡ ブラウザで閲覧中にリアルタイム通信が必要なとき ➡ 業務アプリなど、利用人数が限られたサイトでの レスポンスの向上 ➡ Pushstate(Pjax)と組み合わせてみよう Pjaw Pushstate JavaScript with WebSockethttps://github.com/karad/PlayWebSocketReversi 89
  • 90. 今後の研究課題 ➡ 既存の通信手段とのパフォーマンス比較 ➡ 認証がからむケースのセキュアなWebSocket ➡ WebSocketのデータを保存のベストプラクティス ➡ イベントの登録管理をもっとスマートに ➡ PlayにおけるWebSocketの負荷の調査 ➡ サーバー構成の研究 ➡ ネームスペースの実装(Socket.IO)https://github.com/karad/PlayWebSocketReversi 90
  • 91. ありがとうございました PlayFramework + WebSocket の勉強会 もよろしく http://www.facebook.com/groups/313802075344855/ 詳しくは @kara_d までhttps://github.com/karad/PlayWebSocketReversi 91