一个基于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

用户表:
一个基于SAE Channel的综合应用--mobile web IM(1)_第1张图片 
关系表:
fromUserNum就是自己的num,toUserNum 就是好友的num,toUserNumAlias就是我们对好友设置的别名。一个基于SAE Channel的综合应用--mobile web IM(1)_第2张图片 

好友分组表:
Num是自己的用户名,listName是好友分组名(这是早期的属性名,其实应该叫friendGroupName。。。。)。
一个基于SAE Channel的综合应用--mobile web IM(1)_第3张图片 
关系和好友分组对应表:
toUserNum就是好友的num,listId就是imFriendGroup的id字段。一行记录即代表这个好友在哪个分组里。(其实toUserNum也可以换成关系表的id,但Leonard为了查询方便就这样设计了)
一个基于SAE Channel的综合应用--mobile web IM(1)_第4张图片 
通讯消息表:
isRead为”1”时,表示已发送到对方的client端;为”0”则未发送。
msgUuid,是唯一标识这条记录的,会用到它来update这条记录。但id字段也可以唯一标识,曾经考虑要不要去掉msgUuid。不过先这样吧,以后再看。
一个基于SAE Channel的综合应用--mobile web IM(1)_第5张图片 
好友请求消息表,结构和通讯消息表差不多。
一个基于SAE Channel的综合应用--mobile web IM(1)_第6张图片 
这里就不用什么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
一个基于SAE Channel的综合应用--mobile web IM(1)_第7张图片 


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 移动


你可能感兴趣的:(一个基于SAE Channel的综合应用--mobile web IM(1))