Your SlideShare is downloading. ×
0
PlayFramework 2.0 Javaと       WebSocketでつくる         リアルタイムMVC       Webアプリケーション             原 一浩 @kara_d
原 一浩   @kara_d   NetBeans / SublimeText 2
何してる人?         Greative is Great Creative     デザイントレンド、統計、システム
本日のセッション内容https://github.com/karad/PlayWebSocketReversi   4
本日のセッション内容  サンプルダウンロードURLhttps://github.com/karad/PlayWebSocketReversi   5
目次 ➡   PlayFrameworkとWebSocketの概要 ➡   WebSocketアプリ制作の概要     •   Play 1.2.x     •   Play 2.0 ➡   サンプル:Reversiの実装とデモ ➡   まとめ...
Play Frameworkとはhttps://github.com/karad/PlayWebSocketReversi   7
PlayFrameworkとは ➡   オープンソース(zenexity製) ➡   non Servlet、non XML ➡   ステートレス ➡   MVCフレームワーク ➡   ホットデプロイ ➡   ノンブロッキング IO ➡   H...
PlayFramework 1.2.xまで ➡   テンプレートはGroovy ➡   フルスタック ➡   JPA拡張によるORM ➡   Javaベース ➡   Pythonによるシェル ➡   Scalaモジュールhttps://gith...
PlayFramework 2.0 ➡   テンプレートはScala ➡   モジュール型 ➡   一部ORM選択可能     •   JavaはEBean     •   ScalaはAnormやScalaQuery ➡   Scalaベース...
PlayFramework 2.0 more... ➡   ドキュメントが整備 ➡   サンプルが豊富 ➡   CoffeeScriptサポート ➡   LESSサポート ➡   Google Clojure Compilerサポート ➡   ヘ...
どちらを使うべきか? ➡   安心の1.2.x     •   大量のサードパーティモジュール     •   バグフィックスが進んでいる     •   業務で使用実績 ➡   挑戦の2.0     •   モジュールは、あまりない     ...
ニュース ➡   最近本家のMLがごたごたしてた ➡   今後1.2系はメンテナンスモードに     •   つまり1.3は出ない     •   1.2.5は月末に出るっぽい ➡   2.0は、JavaとScala両方を今後サポートしていく ...
Play 2.0 Overviewhttps://github.com/karad/PlayWebSocketReversi   14
Play 2.0フォルダ ➡   app                             ➡   logs     •   controllers                                     ➡   proj...
Play2.0のサイト構築、基本の流れ(Java) ➡   モデルの構築     •   テスト:Unit Test ➡   コントローラーの構築     •   テスト:Functional Test ➡   ビューの構築     •   テ...
モデル ➡   ORMとしてEBeanを採用 ➡   findやバリデーション(Constraints.*)に対応     @Entity     public	  class	  User	  extends	  Model{     	  	...
コントローラ ➡   基本、Resultを返す     public	  class	  Application	  extends	  Controller	  {     	  	  public	  static	  Result	  i...
レイアウト ➡   レイアウトとビューの区別はない ➡   呼び出しによる入れ子構造     @(title:	  Html,	  nav:	  String	  =	  "")(content:	  Html)     <!DOCTYPE	 ...
ビューテンプレート ➡   main.scala.htmlを呼び出す ➡   引数と内容(content)     @main(Html("Samples"))	  {     	  	  <p>Hello!</p>     }        ...
リアルタイム通信サーバの  これまでhttps://github.com/karad/PlayWebSocketReversi   21
Flashでのリアルタイム通信 ➡   Adobe Flash Communication Server ➡   Adobe Flash Media Server Real Time Messaging Protocol(RTMP) ➡   R...
WebSocketとはhttps://github.com/karad/PlayWebSocketReversi   23
WebSocketは、W3CとIETFが策定 ➡   元々はHTML5の一部 ➡   双方向の通信技術 ➡   AjaxやCommetよりも自然に双方向通信 ➡   コネクション後、専用のプロトコルで通信     •   ハンドシェイク    ...
WebSocket未対応ブラウザへhttps://github.com/karad/PlayWebSocketReversi   25
web-socket-js ➡   https://github.com/gimite/web-socket-js     •   Google Chrome 4 or later, Firefox 6 or later     •   Fir...
PlayFrameworkでの利用 ➡   ダウンロードしたら、     •   public/javascripts/ に「swfobject.js」「web_socket.js」     •   public/swfs/ に「WebSock...
JavaScriptでのWebSocketの接続方法     WEB_SOCKET_SWF_LOCATION	  =	  "SWFを配置したパス";     WEB_SOCKET_DEBUG	  =	  false;     var	  soc...
JavaScriptのWebSocketのAPI ➡   socket = WebSocket(url, protocols) ➡   socket.send() ➡   socket.close() イベントハンドラ ➡   socket.o...
WebSocket通信の確認にはChromeが便利https://github.com/karad/PlayWebSocketReversi   30
PlayFrameworkと  WebSockethttps://github.com/karad/PlayWebSocketReversi   31
Play1.2.3 ➡   hybi-00     •   Chrome 14までサポート Play1.2.4 ➡   hybi-10     •   バージョン8     •   Chrome 16までサポート パッチ(Lighthouse ...
パッチ(Lighthouse 1240 patch)の当て方 ➡   該当のパッチを当てる     •   https://github.com/playframework/play/pull/438 を参照     •   framework...
パッチが当たったリビルド版 ➡   バージョン表記が「play! 1.2.x-localbuild」に     $	  play	  run	  	  	  	  	  	  	  	  	  	  	  	  	  	  	  	  	  	...
Play以外の対応、ご参考まで    •https://github.com/karad/PlayWebSocketReversi   35
WebSocketをフレームワークに載せる意味 ➡   Webアプリケーションとのシームレスな統合 ➡   WebSocketをコントローラーにして設計が容易に ➡   認証系、データ管理系の実装が楽になる WebSocketアプリケーションと...
Play 1.2.4のWebSockethttps://github.com/karad/PlayWebSocketReversi   37
WebSocketController ➡   Staticによるアクション ➡   ルーティングが可能 ➡   InboundとOutboundの2チャンネル ➡   request、params、validation、session ➡  ...
InboundとOutbound ➡   Inbound     •   WebSocketの受信     •   WebSocketのソケットオープン中、 inbound.isOpen()がtrue     •   inbound.nextE...
Outboundあれこれ ➡   テキストフレームは、通常下記みたいな利用をするが、     •   outbound.send("quit:ok"); ➡   JSONでも送信が可能。sendJsonを使用する     •   outboun...
テキストフレームのやりとり ➡   受信     •   play.mvc.Http.WebSocketEvent.TextFrameから         Matcherを使ってtextDataを取り出す     for(String	  te...
PlayFramework 1.2.4でのサンプルhttps://github.com/karad/PlayWebSocketReversi   42
WebSocket:サーバーとクライアント                      PlayFramework        DB                                 WebSocketハンドシェイク       ...
全体構成 ➡   クライアント     •   プロパティを「:」でつないだメッセージ     •   コマンド : ユーザー : メッセージ     •   message : name : text ➡   サーバー     •   Web...
•     各種イベントにマッチするものがあれば、各処理を実行         - WebSocketのイベントが、TextFrameかつTextFrameがquit         - WebSocketのイベントが、TextFrame   ...
ChatModelは、イベント管理モデル ➡   内部にEventクラスというabstractなクラスを用意 ➡   Eventクラスを継承した各種イベントクラス     •   Joinクラス     •   Leaveクラス     •  ...
Play 2.0のWebSockethttps://github.com/karad/PlayWebSocketReversi   47
WebSocket:サーバーとクライアント        DB              PlayFramework         WebSocketハンドシェイク                 1    onReady          ...
WebSocket用コントローラ ➡   Staticによるアクション ➡   ルーティングが可能 ➡   WebSocketオブジェクトの入出力     •   InとOutの2チャンネル ➡   ほとんどの処理はモデルに移動 ➡   onR...
WebSocket対応のコントローラー    public	  static	  WebSocket<JsonNode>	  game(    	  	  	  	  final	  String	  username    	  	  	  ...
WebSocket用モデル ➡   専用のクラス     •   UntypedActor ➡   Akkaベースの非同期プログラミング ➡   同期処理は、Awaitメソッド ➡   In.onMessageと、In.onClose ➡   ...
WebSocket対応のモデルの一部    public	  void	  onReceive(Object	  message)	      	  	  	  	  throws	  Exception	  {    	  	  	  	  ...
AkkaとWebSocketの関係 ➡   WebSocket.In                               WebSocket.In     •   メッセージ受け取り時                          ...
サンプル:Reversihttps://github.com/karad/PlayWebSocketReversi   54
デモ ➡   https://github.com/karad/PlayWebSocketReversihttps://github.com/karad/PlayWebSocketReversi        55
Reversi作成の手順 ➡   Playアプリケーションの作成 ➡   メッセージフォーマットの設計 ➡   イベントモデルの設計 ➡   コントローラ、モデルの作成 ➡   ルーティングの作成 ➡   ビューの作成  【参考】作業ステップを...
Playアプリケーションの作成(1) ➡   システム企画     •   ユーザーは2人(BlackとWhite)の選択     •   盤面をロールオーバーすると相手にも伝わる     •   盤面をクリックすると自分の色に変わる     ...
Playアプリケーションの作成(2) ➡   トップページ                                                                       Login     •   http://U...
Playアプリケーションの作成(3) ➡   コントローラ     •   app/controllers/Application.java         - HTTPリクエストを受けるところ ➡   モデル     •   app/mode...
メッセージのフォーマット(JSON)を決める ➡   kind     •   join、talk、quitの各種フラグ ➡   user     •   ユーザー名(black or white) ➡   x、y ➡   uuid     •...
イベントの種類を決める ➡   各イベントごとにクラスを作成 ➡   public static class     Join(username、channel) … 参加 ➡   public static class     Message...
コントローラの作成(1):Application.java ➡   各種メソッドを実装 ➡   public static Result     index() … トップページ     •   index.scala.html を表示 ➡  ...
コントローラの作成(2):Application.java ➡   public static WebSocket<JsonNode>     game(final String username) … WebSocket     •   Web...
モデルの作成(1):Reversi.javaの構成 ➡   static ActorRef     game … アクター ➡   Map<String, WebSocket.Out<JsonNode>>     members … メンバー一...
モデルの作成(2) ➡   イベント用のインナークラス用意     •   Join                        public	  static	  class	  Join	  {     •   Message      ...
モデルの作成(3) ➡   static ActorRef     game … アクター     static	  ActorRef	  game	  =	       	  	  Akka.system().actorOf(new	  Pr...
モデルの作成(4) ➡   public static void     join(username, in, out) … 参加メソッド     •   接続を行う最初のみ呼び出される     •   ユーザー名と、Inbound、Outbo...
モデルの作成(5) ➡   public void     onReceive(message) … 受信     •   送信されてきたメッセージのクラスによって処理を振分け     •   Joinクラスだった場合         - メン...
onReceiveメソッドの抜粋    public	  void	  onReceive(Object	  message)	      	  	  	  	  throws	  Exception	  {    	  	  	  	  if...
モデルの作成(6) ➡   public void     notifyAll(kind, user, text, x, y, uuid) … 全員に通知     •   各プロパティをJSON形式で格納     •   JSONをメンバー全員...
ルーティングの設定 ➡   ルーティングは、conf/routesファイルを編集     GET	  	  	  	  	  /	  	  	  	  	  	  	  	  	  	  	  	  	  	  controllers.Appl...
ビュー周りの設定(1):ビューですること ➡   レイアウトの用意 ➡   ログイン画面を用意 ➡   ゲーム画面を用意 ➡   ゲーム用のクラスを用意 ➡   通信用のJavaScriptを用意 ➡   マウスイベント用のJavaScript...
ビュー周りの設定(2) ➡   レイアウトの用意     Restful   Make Format   Event Scheme   Model and Controller   Routing   Fronthttps://github.c...
ビュー周りの設定(3) ➡   ログイン画面を用意     Restful   Make Format   Event Scheme   Model and Controller   Routing   Fronthttps://github....
ビュー周りの設定(4) ➡   ゲーム画面を用意     Restful   Make Format   Event Scheme   Model and Controller   Routing   Fronthttps://github.c...
ビュー周りの設定(5) ➡   ゲーム用のクラスを用意           .white            .black          .thinkOut             .thinkOver     Restful   Mak...
ビュー周りの設定(6) ➡   通信用のJavaScriptを用意     •   WebSocketに接続     •   メッセージを受信したら、内容に応じて処理     •   kindがtalkなら、駒の配置もしくはロールオーバーの表示...
ビュー周りの設定(7) ➡   マウスイベント用のJavaScriptを用意     •   mouseover時         - textに"thinkOver"         - x座標、y座標、uuidに $(this).attr(...
WebSocket通信中のJSON ➡   コマンドラインにて確認可能     org.codehaus.jackson.node.ObjectNode@8bfaf9f[     	  	  _children={kind="talk",	  ...
F.javaの話https://github.com/karad/PlayWebSocketReversi   80
F.java:Play 1.2.x ➡   WebSocket周りを見ていくと、必ず当たる壁 ➡   Javaで関数言語的な使い方をサポートするライブラリ     •   Either         - E2、E3、E4、E5まである    ...
パターンマッチFor文:Play 1.2.x    for(String	  a:	  TextFrame.match(e._1))	  {    	  	  	  	  ...処理...    }    for(String	  a:	  T...
F.javaのMatcher周り:Play 1.2.x ➡   String     •   文字列でマッチ ➡   ClassOf     •   クラスでマッチ ➡   StartsWith     •   プレフィックスでマッチ ➡   ...
WebSocketEvent周りのMatcher ➡   SocketClosed.match()     •   WebSocketCloseかどうかでマッチ ➡   TextFrame.match()     •   WebSocketフレ...
F.java:Play 2.0 ➡   Javaで関数言語的な使い方をサポートするライブラリ     •   Either         - E2相当のみになった     •   Callback         - Callback0、Ca...
F.javaの利用について ➡   F.javaはバージョンごとに変化が激しい ➡   現状は読むのみに ➡   WebSocket周りでは必須https://github.com/karad/PlayWebSocketReversi   86
まとめhttps://github.com/karad/PlayWebSocketReversi   87
WebSocketアプリの設計・構築手順 ➡   Playアプリケーションの作成                             Restful ➡   メッセージフォーマットの設計                           ...
WebSocketはどこで役に立つのか? ➡   ログイン以降は、ユーザーによる細かな操作が続く ➡   Ajaxで行ってきた部分の上位バージョンとして ➡   ブラウザで閲覧中にリアルタイム通信が必要なとき ➡   業務アプリなど、利用人数が...
今後の研究課題 ➡   既存の通信手段とのパフォーマンス比較 ➡   認証がからむケースのセキュアなWebSocket ➡   WebSocketのデータを保存のベストプラクティス ➡   イベントの登録管理をもっとスマートに ➡   Play...
ありがとうございました  PlayFramework + WebSocket の勉強会 もよろしく  http://www.facebook.com/groups/313802075344855/  詳しくは @kara_d までhttps:/...
Upcoming SlideShare
Loading in...5
×

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

17,711

Published on

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

Published in: Technology
1 Comment
47 Likes
Statistics
Notes
  • やりたいことの資料
       Reply 
    Are you sure you want to  Yes  No
    Your message goes here
No Downloads
Views
Total Views
17,711
On Slideshare
0
From Embeds
0
Number of Embeds
8
Actions
Shares
0
Downloads
109
Comments
1
Likes
47
Embeds 0
No embeds

No notes for slide

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

  1. 1. PlayFramework 2.0 Javaと WebSocketでつくる リアルタイムMVC Webアプリケーション 原 一浩 @kara_d
  2. 2. 原 一浩 @kara_d NetBeans / SublimeText 2
  3. 3. 何してる人? Greative is Great Creative デザイントレンド、統計、システム
  4. 4. 本日のセッション内容https://github.com/karad/PlayWebSocketReversi 4
  5. 5. 本日のセッション内容 サンプルダウンロードURLhttps://github.com/karad/PlayWebSocketReversi 5
  6. 6. 目次 ➡ PlayFrameworkとWebSocketの概要 ➡ WebSocketアプリ制作の概要 • Play 1.2.x • Play 2.0 ➡ サンプル:Reversiの実装とデモ ➡ まとめhttps://github.com/karad/PlayWebSocketReversi 6
  7. 7. Play Frameworkとはhttps://github.com/karad/PlayWebSocketReversi 7
  8. 8. PlayFrameworkとは ➡ オープンソース(zenexity製) ➡ non Servlet、non XML ➡ ステートレス ➡ MVCフレームワーク ➡ ホットデプロイ ➡ ノンブロッキング IO ➡ HTTPマッピング ➡ テスト環境 ➡ シェルサポートhttps://github.com/karad/PlayWebSocketReversi 8
  9. 9. PlayFramework 1.2.xまで ➡ テンプレートはGroovy ➡ フルスタック ➡ JPA拡張によるORM ➡ Javaベース ➡ Pythonによるシェル ➡ Scalaモジュールhttps://github.com/karad/PlayWebSocketReversi 9
  10. 10. PlayFramework 2.0 ➡ テンプレートはScala ➡ モジュール型 ➡ 一部ORM選択可能 • JavaはEBean • ScalaはAnormやScalaQuery ➡ Scalaベース ➡ SBTによるビルドシステム • 従来のplayコマンドに相当 ➡ Akkaによる非同期処理 ➡ Java/Scalaサポートhttps://github.com/karad/PlayWebSocketReversi 10
  11. 11. PlayFramework 2.0 more... ➡ ドキュメントが整備 ➡ サンプルが豊富 ➡ CoffeeScriptサポート ➡ LESSサポート ➡ Google Clojure Compilerサポート ➡ ヘルパー機能https://github.com/karad/PlayWebSocketReversi 11
  12. 12. どちらを使うべきか? ➡ 安心の1.2.x • 大量のサードパーティモジュール • バグフィックスが進んでいる • 業務で使用実績 ➡ 挑戦の2.0 • モジュールは、あまりない • 出たばかりで、まだバグ多い • 業務実績などもこれから アプリの互換性は、ほぼありませんhttps://github.com/karad/PlayWebSocketReversi 12
  13. 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. 14. Play 2.0 Overviewhttps://github.com/karad/PlayWebSocketReversi 14
  15. 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. 16. Play2.0のサイト構築、基本の流れ(Java) ➡ モデルの構築 • テスト:Unit Test ➡ コントローラーの構築 • テスト:Functional Test ➡ ビューの構築 • テスト:Selenuimベースのfluentleniumhttps://github.com/karad/PlayWebSocketReversi 16
  17. 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. 18. コントローラ ➡ 基本、Resultを返す public  class  Application  extends  Controller  {    public  static  Result  index()  {        return  ok(index.render());    } }https://github.com/karad/PlayWebSocketReversi 18
  19. 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. 20. ビューテンプレート ➡ main.scala.htmlを呼び出す ➡ 引数と内容(content) @main(Html("Samples"))  {    <p>Hello!</p> } index.scala.htmlhttps://github.com/karad/PlayWebSocketReversi 20
  21. 21. リアルタイム通信サーバの これまでhttps://github.com/karad/PlayWebSocketReversi 21
  22. 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. 23. WebSocketとはhttps://github.com/karad/PlayWebSocketReversi 23
  24. 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. 25. WebSocket未対応ブラウザへhttps://github.com/karad/PlayWebSocketReversi 25
  26. 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. 27. PlayFrameworkでの利用 ➡ ダウンロードしたら、 • public/javascripts/ に「swfobject.js」「web_socket.js」 • public/swfs/ に「WebSocketMain.swf」 • 配置し、JavaScript側で呼び出せるようにしたら終わりhttps://github.com/karad/PlayWebSocketReversi 27
  28. 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. 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. 30. WebSocket通信の確認にはChromeが便利https://github.com/karad/PlayWebSocketReversi 30
  31. 31. PlayFrameworkと WebSockethttps://github.com/karad/PlayWebSocketReversi 31
  32. 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. 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. 34. パッチが当たったリビルド版 ➡ バージョン表記が「play! 1.2.x-localbuild」に $  play  run                                                                                             ~                _                        _   ~    _  __  |  |  __  _  _    _|  | ~  |  _  |  |/  _  |  ||  |_| ~  |    __/|_|____|__  (_) ~  |_|                        |__/       ~ ~  play!  1.2.x-­‐localbuild,  http://www.playframework.orghttps://github.com/karad/PlayWebSocketReversi 34
  35. 35. Play以外の対応、ご参考まで •https://github.com/karad/PlayWebSocketReversi 35
  36. 36. WebSocketをフレームワークに載せる意味 ➡ Webアプリケーションとのシームレスな統合 ➡ WebSocketをコントローラーにして設計が容易に ➡ 認証系、データ管理系の実装が楽になる WebSocketアプリケーションとポート ➡ 基本的には、Playが動いているポートになる ➡ Apacheのmod_proxyを経由させている場合は注意https://github.com/karad/PlayWebSocketReversi 36
  37. 37. Play 1.2.4のWebSockethttps://github.com/karad/PlayWebSocketReversi 37
  38. 38. WebSocketController ➡ Staticによるアクション ➡ ルーティングが可能 ➡ InboundとOutboundの2チャンネル ➡ request、params、validation、session ➡ disconnect()で通信の切断 ➡ awaitメソッドで処理の待機 ➡ ビューで、wsプロトコルのURLに • Routesでプロトコルの指定が必要https://github.com/karad/PlayWebSocketReversi 38
  39. 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. 40. Outboundあれこれ ➡ テキストフレームは、通常下記みたいな利用をするが、 • outbound.send("quit:ok"); ➡ JSONでも送信が可能。sendJsonを使用する • outbound.sendJson(Object); ➡ 生データ • send( byte opcode, byte[] data)https://github.com/karad/PlayWebSocketReversi 40
  41. 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. 42. PlayFramework 1.2.4でのサンプルhttps://github.com/karad/PlayWebSocketReversi 42
  43. 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. 44. 全体構成 ➡ クライアント • プロパティを「:」でつないだメッセージ • コマンド : ユーザー : メッセージ • message : name : text ➡ サーバー • WebSocketControllerクラスを継承したChatRoomSocket • ChatRoomSocketには、joinメソッドのみがある • ChatRoomモデル内でチャットのイベントを設定 • inbound.isOpen()の限りループ - Either<WebSocketEvent,ChatRoom.Event> eが評価されない限りは停止https://github.com/karad/PlayWebSocketReversi 44
  45. 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. 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. 47. Play 2.0のWebSockethttps://github.com/karad/PlayWebSocketReversi 47
  48. 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. 49. WebSocket用コントローラ ➡ Staticによるアクション ➡ ルーティングが可能 ➡ WebSocketオブジェクトの入出力 • InとOutの2チャンネル ➡ ほとんどの処理はモデルに移動 ➡ onReady()イベントを定義https://github.com/karad/PlayWebSocketReversi 49
  50. 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. 51. WebSocket用モデル ➡ 専用のクラス • UntypedActor ➡ Akkaベースの非同期プログラミング ➡ 同期処理は、Awaitメソッド ➡ In.onMessageと、In.onClose ➡ onReceive()イベントを定義 ➡ Out.write()で送信 ➡ メンバーとチャンネルhttps://github.com/karad/PlayWebSocketReversi 51
  52. 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. 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. 54. サンプル:Reversihttps://github.com/karad/PlayWebSocketReversi 54
  55. 55. デモ ➡ https://github.com/karad/PlayWebSocketReversihttps://github.com/karad/PlayWebSocketReversi 55
  56. 56. Reversi作成の手順 ➡ Playアプリケーションの作成 ➡ メッセージフォーマットの設計 ➡ イベントモデルの設計 ➡ コントローラ、モデルの作成 ➡ ルーティングの作成 ➡ ビューの作成 【参考】作業ステップをつけています Restful Make Format Event Scheme Model and Controller Routing Fronthttps://github.com/karad/PlayWebSocketReversi 56
  57. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 72. ビュー周りの設定(1):ビューですること ➡ レイアウトの用意 ➡ ログイン画面を用意 ➡ ゲーム画面を用意 ➡ ゲーム用のクラスを用意 ➡ 通信用のJavaScriptを用意 ➡ マウスイベント用のJavaScriptを用意 Restful Make Format Event Scheme Model and Controller Routing Fronthttps://github.com/karad/PlayWebSocketReversi 72
  73. 73. ビュー周りの設定(2) ➡ レイアウトの用意 Restful Make Format Event Scheme Model and Controller Routing Fronthttps://github.com/karad/PlayWebSocketReversi 73
  74. 74. ビュー周りの設定(3) ➡ ログイン画面を用意 Restful Make Format Event Scheme Model and Controller Routing Fronthttps://github.com/karad/PlayWebSocketReversi 74
  75. 75. ビュー周りの設定(4) ➡ ゲーム画面を用意 Restful Make Format Event Scheme Model and Controller Routing Fronthttps://github.com/karad/PlayWebSocketReversi 75
  76. 76. ビュー周りの設定(5) ➡ ゲーム用のクラスを用意 .white .black .thinkOut .thinkOver Restful Make Format Event Scheme Model and Controller Routing Fronthttps://github.com/karad/PlayWebSocketReversi 76
  77. 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. 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. 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. 80. F.javaの話https://github.com/karad/PlayWebSocketReversi 80
  81. 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. 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. 83. F.javaのMatcher周り:Play 1.2.x ➡ String • 文字列でマッチ ➡ ClassOf • クラスでマッチ ➡ StartsWith • プレフィックスでマッチ ➡ Re • 正規表現パターンでマッチ ➡ Equals • 等価な文字列でマッチhttps://github.com/karad/PlayWebSocketReversi 83
  84. 84. WebSocketEvent周りのMatcher ➡ SocketClosed.match() • WebSocketCloseかどうかでマッチ ➡ TextFrame.match() • WebSocketフレームがバイナリでなく、なおかつtextDataでマッチ ➡ BinaryFrame.match() • WebSocketフレームがバイナリで、binaryDataでマッチhttps://github.com/karad/PlayWebSocketReversi 84
  85. 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. 86. F.javaの利用について ➡ F.javaはバージョンごとに変化が激しい ➡ 現状は読むのみに ➡ WebSocket周りでは必須https://github.com/karad/PlayWebSocketReversi 86
  87. 87. まとめhttps://github.com/karad/PlayWebSocketReversi 87
  88. 88. WebSocketアプリの設計・構築手順 ➡ Playアプリケーションの作成 Restful ➡ メッセージフォーマットの設計 Make Format ➡ イベントモデルの設計 Event Scheme ➡ コントローラ、モデルの作成 Model and Controller ➡ ルーティングの作成 Routing ➡ ビューの作成 Front クラスベースハンドラのイベント駆動プログラム関数型風味 WebSocketは、チャットを作るための機能ではないhttps://github.com/karad/PlayWebSocketReversi 88
  89. 89. WebSocketはどこで役に立つのか? ➡ ログイン以降は、ユーザーによる細かな操作が続く ➡ Ajaxで行ってきた部分の上位バージョンとして ➡ ブラウザで閲覧中にリアルタイム通信が必要なとき ➡ 業務アプリなど、利用人数が限られたサイトでの レスポンスの向上 ➡ Pushstate(Pjax)と組み合わせてみよう Pjaw Pushstate JavaScript with WebSockethttps://github.com/karad/PlayWebSocketReversi 89
  90. 90. 今後の研究課題 ➡ 既存の通信手段とのパフォーマンス比較 ➡ 認証がからむケースのセキュアなWebSocket ➡ WebSocketのデータを保存のベストプラクティス ➡ イベントの登録管理をもっとスマートに ➡ PlayにおけるWebSocketの負荷の調査 ➡ サーバー構成の研究 ➡ ネームスペースの実装(Socket.IO)https://github.com/karad/PlayWebSocketReversi 90
  91. 91. ありがとうございました PlayFramework + WebSocket の勉強会 もよろしく http://www.facebook.com/groups/313802075344855/ 詳しくは @kara_d までhttps://github.com/karad/PlayWebSocketReversi 91
  1. A particular slide catching your eye?

    Clipping is a handy way to collect important slides you want to go back to later.

×