Lotus Sametime 开发入门: 使用客户端 ToolKit 与 Sametime 服务器交互 |
级别: 初级 刘 欣 (liuxinlx@cn.ibm.com), 软件工程师,IBM CSDL 2006 年 6 月 22 日 本篇文章作为 Lotus Sametime toolkit 开发入门系列的第一篇,将重点介绍客户端 Java toolkit 的使用方法,并带领读者循序渐进的开发出两个简单的 Sametime Java 客户端程序。 通常来讲,一个好的平台产品除了自身的强大功能外,还应该是开放的,使得开发人员能够进行二次开发和定制,从而扩展平台的功能。Lotus Sametime作为IBM市场领先的,企业级实时协作的平台,就符合这两个特征:自身具备强大的Instant Messaging和Web Conferencing能力,同时还开放了一系列API给开发人员使用。这些API被组织成多个toolkit开放出来。本系列入门文章将详细介绍这些toolkit,以帮助开发人员了解如何使用在Sametime平台上开发。 从开发人员的角度看,这些toolkit可分为客户端和服务器端。客户端提供与Sametime服务器进行交互的能力,利用它提供的服务和组件,开发人员可以很轻松的把Sametime的相关功能嵌入到自己的应用程序中,比如在线聊天、会议、视频等,甚至开发自己的即时通讯软件。 服务器端toolkit则提供对Sametime服务器进行扩展的API。开发人员可以把自己的应用程序以类似于插件的方式插入Sametime服务器。例如简单的"机器人"程序,向用户提供实时的股票,天气等信息;"离线消息"程序,能够向离线用户发送消息,复杂的应用例如拍卖程序,在线游戏等等。 本篇文章作为Lotus Sametime toolkit开发入门系列的第一篇,将重点介绍客户端java toolkit的使用方法,并带领读者循序渐进的开发出两个简单的Sametime java客户端程序。 Lotus Sametime是IBM市场领先的、企业级实时协作的平台。它具备强大的实时通信,在线会议的功能,全世界每天都有超过1500万人在使用Sametime及相关软件。 Lotus Sametime一个典型的C/S应用。各个客户端都需要登录到服务器并通过服务器发送各种消息。 图1:Sametime体系结构图
Sametime toolkit可以从IBM developerWorks Lotus Toolkits页面上下载. 该页面上包括从版本3.1, 6.5.1到7.0的所有服务器端和客户端的toolkit下载链接。 下表列出了客户端toolkit的不同版本:
本文以Java toolkit为例来介绍其使用方法,下文中如果没有特殊说明,当提到toolkit时,均是指Java toolkit。
"分层"在软件系统中是个非常有效的解决问题的方法,Sametime java toolkit也划分为3个层次:UI Layer, Server Layer, Transport Layer。他们之间的关系如下图所示: 图2:Sametime toolkit体系结构图 1.传输层(Transport Layer): 位于体系结构的最底层,负责处理和Sametime服务器的通信。开发人员不必关心这一层。 2.服务层(Service Layer): 如下图所示,这一层提供了两大类服务:Community类服务和Meeting类服务,每一类服务都包含了多个具体的服务(Service)。本文将着重介绍这些服务的使用方法。 图3:Sametime服务结构图 Community类服务中的较常用服务包括:
Meeting类服务中常用服务有:
3.UI层: 位于toolkit体系的最上层,它提供了多种UI组件方便程序员开发,例如:只需要简单的调用Chat UI的几个方法,就能提供一个简单的聊天界面。使用UI层的API可以极大的简化程序员的开发工作。
限于篇幅,本文不可能涉及的介绍客户端toolkit中的所有服务。本文将随着介绍客户端toolkit中的最重要服务带领读者完成一个简单的登录聊天的应用程序(STClient)。有兴趣的读者可以自行阅读本文列举的参考资料和客户端toolkit自带的其他示例程序。 开发完成后,读者可以通过此示例程序完成如下功能:
该程序界面如下图所示: 图4:Sametime客户端示例程序:STClient 为了便于读者理解,本文中的代码只是从程序中摘取的一些片断并做了少许修改,完整的代码可以在参考资料中下载。 Community类服务1. Community服务(CommunityService): 登录Sametime服务器 STClient 程序要做的第一步就是登录到Sametime服务器, 这就需要使用toolkit中最基本的一个服务CommunityService,通过它才能登录到Sametime 服务器。另外该服务还可以接收管理员消息,改变用户状态和隐私设置。使用该服务登录到Sametime需要下面几个步骤 步骤一:创建Session对象
上面的代码片断首先创建一个STSession 对象,通过它才能装入Sametime的所有服务,在本例中根据我们的需求使用了loadSemanticComponents()方法,toolkit也提供了其他方法来装载特定的服务,请参考相关文档。在STSession使用之前,我们必须调用它的start()方法。 步骤二:,获得Community服务对象并登录 我们需要通过session对象获得CommunityService的引用并使用loginByPassword()方法登录。注意所有的Sametime的组件都有COMP_NAME属性。
loginByPassword的三个参数分别是sametime server 地址,用户名和密码 步骤三:实现LoginListener 因为Sametime是在网络上运行的程序,所以登录过程可能需要一定时间。我们不希望程序一直等待登录成功的确认,所以我们需要实现Listener接口让Community服务在登录成功后通知程序。 因此我们需要为Community服务对象绑定LoginListener并实现LoginListener接口的两个方法:loggedIn()和loggedOut()。 首先在调用loginByPassword()方法前增加语句
然后在LoginHandler类中实现LoginListener接口。
步骤四:注销 最后,不要忘记,在程序关闭时,必须要关闭并注销所有Sametime对象。
通过以上这四步,我们可以看到Sametime中基本的设计模式:观察者模式(Observer pattern)。在客户端向服务器发出请求之前(比如Login),先创建一个观察者(如LoginListner的实现类),把它加入到适当的组件中去。这样请求完成以后,观察者的相关方法会被调用(如loggedIn()方法),对结果(比如登录是否成功)进行处理。观察者模式在对Sametime的编程中几乎无处不在,下文中会有更多的示例。 本小节详细的代码参见示例程序STClient类。 2. Lookup服务(LookupService):查找用户 登录到系统以后,在向任何一个用户发送消息之前,我们先要获得这个用户的引用。在Sametime toolkit中,用户(User)模型非常重要。简单的来讲,该模型包括静态的User和动态的User, 静态User代表Sametime community中的一个实体,在toolkit中与之对应的是STUser类。一旦用户登录到系统中以后,就产生了一个动态的User, 可用STUserInstance来表示。如果一个用户登录多次,就会产生多个不同的STUserInstance对象。在这里我们只需要获得STUser对象的引用。 步骤一:获得LookupService对象 同获得CommunityService对象相似,我们通过调用STSession的getCompApi方法,传入LookupService的COMP_NAME属性,并通过强制类型转换获得LookupService的引用。
步骤二:解析用户 解析用户需要使用Resolver类。我们首先用LookupService对象创建Resolver类,然后使用该类的resolve()方法解析指定用户。
步骤三:实现ResolveListener 同样,由于在网络上解析用户需要一定时间,我们使用观察者模式接收解析结果消息。这里需要实现ResolveListener接口和它的三个方法。 首先在调用resolve()方法前增加语句:
然后在ResolveHandler中实现ResolveListener接口。如果解析成功,resolved()方法将会被调用。在本例中,如果解析失败或解析到多个用户,我们不作任何处理。
本小节详细的代码参见示例程序AddUserDialog类 3. Instant Messaging服务(InstantMessagingService):进行实时交谈现在我们已经可以获得一个用户的实例,接下来希望向一个指定用户发送/接收即时消息(Instant Message),这就需要使用Instant Messaging服务。用法是先创建一个IM对象,该对象代表了两个Client之间的一次会话,然后通过IM对象能够发送和接收消息。需要注意的是IM必须被打开以后才能使用。 步骤一: 获得InstantMessagingService对象 首先像创建其他服务对象一样,通过STSession对象获得InstantMessagingService对象。
步骤二: 打开即时消息(IM) 打开即时消息需要使用Im类。我们首先用InstantMessagingService对象创建Im类,然后使用该类的open方法打开即时消息。
在createIm()方法中,参数stUser表示和指定的用户创建一个IM会话, encLevel表示加密级,imType表示IM的类型,常用的是ImTypes.IM_TYPE_CHAT。 步骤三: 实现Listener 同样,我们使用观察者模式接收消息。这里需要实现两个Listener接口。
首先在调用open()方法前增加语句:
然后分别实现这两个Listener接口。
假设用户A希望向用户B发送消息,他创建了一个Im对象,添加了ImHandler,然后调用open()方法打开了它,那么在用户B处imReceived()方法就会被触发,用户B在接收到一个用户A创建的IM后,也需要为这个IM添加一个ImHandler对象,以便进行消息的处理 ImListener的实现如下:
可以看出,ImHandler能够对多个事件进行响应,常用到的两个方法是: 1.imOpened():它表示IM已经打开成功,可以发送/接收消息了,在我们的例子中立刻调用了IM的sendText方法发送了一个简单的消息。 2.textReceived():它利用ImEvent参数能够取得对方发送过来的消息。 本小节详细的代码参见示例程序ChatFrame类。 4. Places服务(PlacesService):在虚拟空间中进行协作 Place在Sametime toolkit中是非常重要的结构,它作为一个虚拟的空间,多个用户可以在其中进行协作,在应用程序中使用一个字符串名称和类型来标志Place。Place中包括三类成员:User, Section和Activity。
关于Place的另一个基本概念是Place Member。User,Section,Activity甚至Place本身都是Place Member,下面是它们之间的关系图。 图5:Sametime place模型 Place Member定义的接口允许成员之间通过发送消息/数据的方式进行通信。但是对不同的Place Member调用sendText()方法,接收者的范围(Scope)有所不同。例如place.sendText() 会导致Place中的所有成员都会接收到消息,而section.sendText()则把范围限定到一个特定Section中。 在我们的例子STClient中,Place会作为一个桌面共享的空间,这一小节只介绍如何进入Place, 其他操作在读者能在Application Share服务一节中看到。 步骤一:获得Place Service 首先像创建其他服务对象一样,通过STSession对象获得PlacesService对象。
步骤二:创建并进入Place
步骤三:实现Listener 我们仍然使用观察者模式接收消息。虽然可以实现PlaceListener接口来接收消息,但toolkit中提供了更加方便使用的PlaceAdapter类。因为它已经实现了全部PlaceListener接口,我们只需继承它并重载需要改变的方法即可。 首先在调用enter()方法前增加语句:
然后在PlaceHandler中重载PlaceAdapter的方法。作为例子,这里我们只重载entered()方法。
本小节详细的代码参见示例程序AbstractDesktopSharing类。 Meeting类服务 1.Application Share服务(AppShareService):共享桌面 到此为止,我们已经实现了登录、查找用户、和实时交谈的功能,接下来编写Application Share的代码。它允许几个在线的用户之间共享、操作某一个用户机器上的桌面或程序。正如介绍Place时提到的,Application Sharing 和下面要介绍的Whiteboard实际上都属于Place中的Activity。开发人员需要进入到一个Place中,添加一个特定类型的Activity, 然后才能进入后续操作。 步骤一:创建Application Share Service
MeetingFactoryComp用于维护到Server的连接,这些连接会被Application Sharing, Whiteboard,Audio/Vedio等组件所使用,所以必须创建一个MeetingFactoryComp实例。注意这里和上述的Service用法有所不同,并不是通过session.getCompApi()方法来获取,而是直接"new"一个组件服务。 步骤二:创建Place对象 在Places服务中已经介绍过,略 步骤三:添加PlaceListener,进入到Place 在Places服务中已经介绍过,略 步骤四:添加AppShare Activity 在PlaceHandler的entered()中,我们增加了一个Activity.
步骤五:操作AppShare对象 当Activity被成功添加以后,PlaceHandler的activityAdded()方法会被调用,在该方法中可以获得AppShare对象,并且增加一个AppShareListener。这个Listener会通知AppShare对象是否可以使用了。 方便起见,我们假设用户A的机器桌面将要被共享,而用户B的将要显示、操作用户A的桌面。 先来看用户A机器上的代码:
如果运行成功,在用户A的机器上会出现下图所示的工具条,允许用户进行控制 对于用户B来讲,只需要改变AppShare对象的Listener即可 ……
如果运行成功,则用户B的机器上就能显示用户A的桌面了。 本小节详细的代码参见示例程序AbstractDesktopSharing,DesktopSharingHost和DesktopSharingViewer。 2.Whiteboard服务(WhiteboardService) Whiteboard Service提供一个虚拟的"白板",多个用户可以在其中进行基本的图形操作。它的使用方法和Application Sharing Service非常类似。读者可以自行实现。 Sametime Java toolkit 中内置了一系列UI对象,使用这些UI对象可以极大的简化Sametime客户端软件的开发。这些UI组件也分为两类,一类是对话框和面板(Panel),一类称之为UI组件。 对话框和面板类UI对象包括:
UI组件包括:
注意在使用上述所有对象前,必须先将它们装入STSession对象。为了简化,我们可以使用下面的语句装入全部组件:
这两种UI对象的区别是:对话框和面板和面板对象都需要通过构造器生成,即使用new关键字。而UI组件和服务层的对象类似,要使用STSession的getCompApi方法装入。 在所有UI对象中,最为复杂的是用户状态感知列表(AwarenessList)组件。使用它我们几乎可以完成一个简单Sametime客户端程序的全部功能。而其他大部分UI组件的功能在用户状态感知列表组件中都可以找到。因此我们将重点介绍用户状态感知列表组件,并给出一个只使用用户状态感知列表组件和添加用户对话框组件的示例程序STUIClient。该示例除没有会议功能外,其他功能与服务层介绍的示例程序STClient基本相同,但代码量只是该程序的四分之一。 下面是示例程序的界面: 图6:Sametime客户端UI示例程序:STUIClient 用户可以在列表中添加用户,并选择与在线用户交谈。同样为了便于读者理解,本文中的代码只是从程序中摘取的一些片断并做了少许修改,完整的代码可以在参考资料中下载。 对话框和面板 1. 添加用户对话框(AddDialog) 我们可以通过如下方法弹出一个添加用户对话框: 步骤一:创建并打开对话框
步骤二:实现listener 首先在调用setVisible()方法前增加语句:
注意AddDialog 的addResolveViewListener()方法要求使用ResolveViewListener接口。如果解析成功,该接口的resolved()方法将会被调用。在本例中,如果解析失败或解析到多个用户,我们不作任何处理。如果解析到多个用户,添加用户对话框会列出所有匹配的用户以供选择。
2. 解析用户面板(ResolvePanel) 由于添加用户对话框已经实现了解析用户面板的基本功能,我们在这里不再作详细介绍。有兴趣的读者可以自行参考客户端toolkit中的示例程序ResolveApplet。 3. 用户状态感知列表(AwarenessList) 用户状态感知列表的用法如下: 步骤一:创建AwarenessList对象并将它添加到AWT容器中
步骤二:添加用户
AddUser()可以在任何需要添加用户时调用。在示例程序中,我们分别在loggedIn()方法中添加自己,和在resolved()中添加解析成功的用户。 我们不需要添加任何listener,用户状态感知列表就可实时监听并显示列表上任何用户状态的变化。 使用用户状态感知列表组件,我们还可以在任何在线用户上单击右键并选择交谈,发送通知或发送文件。 4. 空间用户状态感知列表(PlaceAwarenessList) 虚拟空间用户状态感知列表组件与用户状态感知列表组件用法类似,此处不再赘述。有兴趣的读者可以自行参考客户端toolkit中的示例程序PlaceAwareness。 5. 目录面板(DirectoryPanel) 由于添加用户对话框已经实现了解析目录面板的基本功能,我们在这里不再作详细介绍。有兴趣的读者可以自行参考客户端toolkit中的示例程序Directory。 6. 隐私设置面板(PrivacyPane1) 限于篇幅我们不再详细介绍隐私设置面板,有兴趣的读者可以自行参考客户端toolkit中的示例程序PrivacyApplet。 UI组件 1. 通知组件(AnnouncementUI) 我们可以通过如下方法弹出一个通知对话框: 步骤一:获得AnnouncementUI组件对象。
步骤二:发送通知。
注意这里的users是STObject的数组。即通过该方法我们可以同时向多个用户或用户组发送通知。 在运行完上述语句后,程序会弹出对话框请求用户确认。用户点击"发送"按钮即可向指定用户发送通知。 接收通知对话框不需要任何代码。我们只需要将通知组件装入Sametime的STSession对象中,通知组件会自动监听通知事件并在收到通知时弹出对话框。 2. 聊天组件(ChatUI) 聊天组件是4个UI组件中最为复杂的一个。聊天组件有如下重要方法:
我们在这里只演示如何创建一个1对1的对话: 步骤一:获得ChatUI组件对象。
步骤二:发起交谈
聊天组件的会议功能是通过浏览器实现的。关于示例代码有兴趣的读者可以自行参考客户端toolkit中的示例程序ChatUIApplet。 我们还可以通过扩展DefaultChatFactroy定制聊天窗口。请参见客户端toolkit中的示例程序CustomizeChatUI。 3. 社区组件(CommUI) 社区组件比较简单但也是最为常用的组件。我们经常需要使用这个组件解析用户名。我们在介绍Lookup服务和添加用户对话框时有使用Resolver类和ResolveViewListener接口解析用户的例子,这里我们也可以使用社区组件解析用户。方法如下: 步骤一:获得CommUI组件对象
步骤二:解析用户
步骤三:实现listener 在resolve()方法前添加语句。
然后在ResolveHandler中实现CommUIListener接口。如果解析成功,resolved方法将会被调用。在本例中,如果解析失败或解析到多个用户,我们不作任何处理。
注意我们不需要实现resolveConflict()方法。因为在解析到多个用户时,社区组件会自动弹出对话框让用户选择正确的用户。 显示注销信息和显示管理员公告信息不需要任何代码,只需将社区组件装入Sametime的STSession对象中即可,社区组件会自动监听事件并弹出相应对话框。 4. 文件传输组件(FileTransferUI) 发送文件的方法如下: 步骤一:获得FileTransferUI组件对象
步骤二:发送文件
显示接收文件对话框不需要任何代码,只需将文件传输组件装入Sametime的STSession对象中即可,组件会自动监听事件并弹出相应对话框。
我们可以看到,实现同样的功能,使用UI组件会使用极大的节省代码。因此如果读者对自己Sametime客户端程序的界面没有特殊要求,可以尽量使用内置的UI组件。否则就需要使用相应的服务类自己实现这些功能。 在Sametime客户端的toolkit中自带的大量的示例代码,读者也可以阅读这些代码以进一步加深对toolkit的了解。
|