一個基於SAE Channel的綜合應用--mobile web IM(1)

關鍵詞:Mobile IM, SAE Channel, JQM動態加載, 滾動刷新,設計模式,編程範式
Hi, 我是Leonard,應小虎哥的要求,把本身業餘時間作的一個基於Channel的mobile IM以帖子形式共享出來,徹底是Leonard本人一人開發,歡迎你們指出改進的地方。原本不太好意思把這個APP發表出來的,可答應了小虎,那就醜婦見家翁吧。

文章有點長,介紹了Channel的綜合應用, JQM的動態加載、滾動刷新,Scala語言的特性(無論童鞋們從此搞不搞scala,Java8的新特性多多少少和scala相似),和一些簡單的設計模式和編程範式。但願你們能和Leonard能對此進行交流,併爲SAE加油(SAE的服務真的很好,至少對比那麼多家cloud platform後,SAE仍是不錯的)。

在此以前,已經有不少大牛寫了關於channel介紹、配置和開發的文章了,請參考:http://cloudbbs.org/forum.php?mod=viewthread&tid=20008&highlight=channel
http://cloudbbs.org/forum.php?mod=viewthread&tid=19791&highlight=channel等,這裏再也不敘述。

App和手Q相似,登陸,發消息等,功能較簡單,界面也參考了手Q,只不過如今咱們要用的是channel來實現。先看youku上的在window chrome的演示。App目前也僅支持Chrome(由於用了websql)
視頻地址
http://v.youku.com/v_show/id_XNjYwNDcwOTQw.html
http://v.youku.com/v_show/id_XNjYwNDc1NTg4.html
http://v.youku.com/v_show/id_XNjYwNDQ0MjM2.html

APP地址
http://pabushai.sinaapp.com/page/
下面開始介紹,app使用了多種不一樣的技術,不過咱們仍是重點討論Channel,以避免跑題(考試做文跑題但是沒有分的啊!!!)。
因涉及到的代碼有點多,Leonard就不打算以各個代碼結構爲單元的方式敘說,而採用功能流程的方式,即代碼走到哪裏,咱們就講解哪裏,這樣容易串起來。OK,Let’s begin!

1. 整體結構

1.1 DB

用戶表:
 
關係表:
fromUserNum就是本身的num,toUserNum 就是好友的num,toUserNumAlias就是咱們對好友設置的別名。 

好友分組表:
Num是本身的用戶名,listName是好友分組名(這是早期的屬性名,其實應該叫friendGroupName。。。。)。
 
關係和好友分組對應表:
toUserNum就是好友的num,listId就是imFriendGroup的id字段。一行記錄即表明這個好友在哪一個分組裏。(其實toUserNum也能夠換成關係表的id,但Leonard爲了查詢方便就這樣設計了)
 
通信消息表:
isRead爲」1」時,表示已發送到對方的client端;爲」0」則未發送。
msgUuid,是惟一標識這條記錄的,會用到它來update這條記錄。但id字段也能夠惟一標識,曾經考慮要不要去掉msgUuid。不過先這樣吧,之後再看。
 
好友請求消息表,結構和通信消息表差很少。
 
這裏就不用什麼ER圖和UML了,結構很簡單。

1.2
projects
 
LeoWebAppServer是web工程,就是咱們存放servlet等的地方。
LeoEntity是實體類,其餘工程都用到。
LeoDao是進行DB持久化的工程。
LeoAction是進行request處理的地方。
CordovaExample是一個phonegap工程,自己此APP是一個phonegap項目,不過如今以web的形式部署。其實只要以phonegap形式打包,此APP就搖身一變變成Android或iOS app了,但此本文不會描述該工程,在這裏提到只是想說明咱們的web工程也能夠靈活地轉爲Android或iOS app,使用手機的拍照、geolocation、搖一搖等多項有趣的功能,又多了一個選擇。
工程的大概調用流程:瀏覽器->LeoWebAppServer->LeoAction->LeoDao->DB,而LeoEntity被各個工程引用。

1.3
用到的技術
Browser端:iScroll + jQuery + jQueryMobile + webSQL/IndexedDB + SAE Channel client lib + etc
Server端:scala + java + SAE Channel server lib
DB: mysql

1.4
主要功能
註冊,登陸,好友查找,聊天,心跳和斷線重連,消息查看等

1.5
主要特點
實時消息、動態加載、滾動刷新、瀏覽器本地存儲、消息提醒氣泡。

2. 登陸功能

2.1 登陸頁面
index.html
 


2.2
點擊登陸,獲取channel URL
從index.html咱們能夠看到,登陸其實是調用leo.leoChannel.loginServer($('#num').val(), $('#pwd').val(), true);
咱們看一下類leo.LeoChannel:
clientActionChannel.js
leo.LeoChannel負責鏈接server,收、發消息,就是和server通訊的類。
loginServer方法中,對當前的鏈接狀態做了一些判斷,實際上調用的是connectAndThenLogin和getChannelUrlAndConnect方法。
在getChannelUrlAndConnect方法中,咱們用Ajax調用LeoWebAppServer工程的一個servlet,該servlet會新生成一個channel URL,供瀏覽器鏈接到該channel。

2.3
生成channel URL
SaeChannelUrlCreator.java

重點看CreateSaeChannel方法,先以UUID做爲channel的name來生成一個channel, 而後new一個SaeChannelWrapper,把channel對象塞進去,最後是以JSON的方式把channel URL返回給browser。

2.4
快遞SaeChannelWrapper
SaeChannelWrapper.java

我是專門負責收發消息的…快遞….??。
這個類包含了channel,用戶信息等屬性。先提到注意下onTextMessage方法,咱們用channel發送消息的時候,會調用該方法,也就是說這個類是收發消息的,很簡單,你們不要搞複雜了。
SaeChannelUrlCreator中調用了onopen,中間用到了LeoSocketManager,咱們接下來研究他。
2.5
快遞的頭兒LeoSocketManager
LeoSocketManager.scala

我是管理大家這些快遞的頭,想拿獎金就得多送點快遞。不過咱們過年停業:)。
很差意思了各位Javaer,Leonard要開始講Scala代碼了。沒搞過?不用怕,它們語法很像,也是編譯爲byte code在JVM上執行。
(插個題外話,嫌長可略過。選擇Scala是由於它的flexibility,強大的語法,模式匹配,雖然TIOBE世界編程語言排行榜三十多位,但論靜態編譯性和執行性能,它絕對是Java在JVM上候選語言的前列。學習scala的同時還能掌握functional paradigm(函數式編程範式)。Java8其實多少也借鑑了Scala。Leonard在開發的過程當中也是在學習scala,若是有scala高手還請提些建議)。
此快遞頭兒有三個主要的屬性,實際上都是Map集合:
1)loginSockets:凡是登陸成功的用戶都放進來,key爲user num(登陸頁面輸入的用戶名),value是一個IImSocket的Set集合,爲何是set? 意思是能夠保存多個快遞channel,一個用戶可進行屢次登陸,向此用戶發消息則全部的channel都能收到。要想惟一性登陸,在登陸時判斷一下就行了,設計成set是想具備靈活性。
2)rawSockets: 鏈接了channel但未登陸成功的用戶都放進來,類型爲set。不多用。
3)Channels:專門爲SAE channel新建的Map。在Leonard用SAE channel前,此APP是用websocket實現的,而且loginSockets是以user num爲key。但用了SAE channel,不能以user num爲key了,由於不惟一,所以Channels 的key爲channel name(即UUID),value爲抽象接口快遞IImSocket(SaeChannelWrapper實現了此IImSocket接口)。
提高:目前此快遞頭是住在咱們普通的內存裏,而且使用了synchronized來同步操做,這樣並很差。後邊打算使用SAE的KVDB,有這方面的專家還請不吝賜教。

2.6
Channel URL回到客戶瀏覽器
好了,server返回了Channel URL,而且該緩存的channel都緩存了,也初始化了,下來又該JS活躍了。
clientActionChannel.js
繼續getChannelUrlAndConnect方法。在success回調方法中,有2行代碼:socket = esto.CreateSocket(e.url); esto.setHandlersForSocket(obj);
第一行實際上就是調用sae.Channel(url); 並賦值給socket變量(socket就是channel,一個東西)。由於以前是用websocket來new window.WebSocket(_url),因此作了抽象,不直接調用SAE API。
第二行是對socket變量進行事件回調配置。
後續:
一個基於SAE Channel的綜合應用--mobile web IM(2)
http://cloudbbs.org/forum.php?mod=viewthread&tid=20301

一個基於SAE Channel的綜合應用--mobile web IM(3)
http://cloudbbs.org/forum.php?mod=viewthread&tid=20302

一個基於SAE Channel的綜合應用--mobile web IM(4)
http://cloudbbs.org/forum.php?mod=viewthread&tid=20304




本主題由 zhaixiaohu 於 2014-1-14 13:17 移動php

相關文章
相關標籤/搜索