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