到非常多开发IM系统的朋友都想实现聊天记录存储和查询这一不可或缺的功能,这里我就把自己前段时间为傲瑞通(OrayTalk)开发聊天记录模块的经验分享出来,供须要的朋友參考下。

一.整体设计

1.存储位置  

从一開始我们就打算在服务端和client本地同一时候存储聊天记录。并且,在client查看聊天记录时。能够选择是从本地载入、还是从server载入。这样做的优点有两个:

(1)从本地载入聊天记录速度很快。

(2)当更换了登录的机器,在不论什么地方不论什么时刻都能够从server载入完整的聊天记录,记录永远不会丢失。

2.存储方案

(1)在服务端存储聊天记录当然使用我们主流的数据库SqlServer或Mysql等。

(2)在client,我们開始选择的是使用序列化技术。可是。考虑到当聊天记录数据量庞大时,序列化方案就不够灵活了。并且性能也跟不上。所以,最后决定使用轻量级的数据库Sqlite。

3.ORM框架

  DataRabbit的最新版本号添加了对Sqlite的支持,而且对不同数据库的操作API是全然一致的。所以我们使用DataRabbit写了一个小组件来完毕聊天记录的存储与查询等数据库訪问操作。

而不管是client还是服务端的聊天记录存储相关的工作,都交给这个组件来完毕。

二.详细实现

1.ChatMessageRecord类

  一条聊天记录基本上包括了下面几个内容:发送人、接收人、内容、时间等。

而且,我们想将两人聊天及群聊天抽象成同一个模型,于是,聊天记录的Entity类ChatMessageRecord设计成例如以下模样:

    public class ChatMessageRecord
{
#region AutoID
private long autoID = 0;
/// <summary>
/// 自增ID,编号。
/// </summary>
public long AutoID
{
get { return autoID; }
set { autoID = value; }
}
#endregion #region SpeakerID
private string speakerID = "";
/// <summary>
/// 发言人的ID。
/// </summary>
public string SpeakerID
{
get { return speakerID; }
set { speakerID = value; }
}
#endregion #region AudienceID
private string audienceID = "";
/// <summary>
/// 听众ID。能够为GroupID。 /// </summary>
public string AudienceID
{
get { return audienceID; }
set { audienceID = value; }
}
#endregion #region OccureTime
private DateTime occureTime = DateTime.Now;
/// <summary>
/// 聊天记录发生的时间。 /// </summary>
public DateTime OccureTime
{
get { return occureTime; }
set { occureTime = value; }
}
#endregion #region ContentRtf
private string contentRtf = "";
/// <summary>
/// 聊天的内容。
/// </summary>
public string ContentRtf
{
get { return contentRtf; }
set { contentRtf = value; }
}
#endregion #region IsGroupChat
private bool isGroupChat = false;
/// <summary>
/// 是否为群聊记录。
/// </summary>
public bool IsGroupChat
{
get { return isGroupChat; }
set { isGroupChat = value; }
}
#endregion
}

    在ChatMessageRecord的定义中。聊天内容字段被设计为string类型,这是由于在OrayTalk中,聊天内容是富文本RTF格式的。

假设须要,能够更改为byte[]类型,这样通过自己定义的序列化操作就能够承载更复杂的聊天格式。

  最后一个字段IsGroupChat表明当前记录是否为群聊记录,假设是群聊记录,那么,AudienceID就不是好友的ID了,而是目标群组的ID。

  最后请注意:ChatMessageRecord实体与数据库中的ChatMessageRecord表是全然映射的关系,这才使得DataRabbit的ORM数据訪问成为可能。

2.ChatRecordPage类

  当我们请求聊天记录时,因为记录数量可能很庞大,所以。採用分页是不可避免的。我们用ChatRecordPage来封装查询返回的一页聊天记录:

依据ChatRecordPage中的TotalCount字段,查询者能够知道符合条件的记录数是多少,如此,就能够知道总共同拥有多少页。

3.IChatRecordPersister接口

  不管是client还是服务端存储与查询聊天记录。我们都使用同一个接口IChatRecordPersister来进行抽象:

    public interface IChatRecordPersister
{
/// <summary>
/// 插入一条聊天记录(包含群聊天记录)。 /// </summary>
void InsertChatMessageRecord(ChatMessageRecord record); /// <summary>
/// 获取一页与好友的聊天记录。 /// </summary>
/// <param name="timeScope">日期范围</param>
/// <param name="myID">自己的UserID</param>
/// <param name="friendID">好友的ID</param>
/// <param name="pageSize">页大小</param>
/// <param name="pageIndex">页索引</param>
/// <returns>聊天记录页</returns>
ChatRecordPage GetChatRecordPage(DateTimeScope timeScope, string myID, string friendID, int pageSize, int pageIndex); /// <summary>
/// 获取一页群聊天记录。 /// </summary>
/// <param name="timeScope">日期范围</param>
/// <param name="groupID">群ID</param>
/// <param name="pageSize">页大小</param>
/// <param name="pageIndex">页索引</param>
/// <returns>聊天记录页</returns>
ChatRecordPage GetGroupChatRecordPage(DateTimeScope timeScope, string groupID, int pageSize, int pageIndex);
}

(1)插入游戏记录时,与好友聊天记录以及群聊天记录使用同一个InsertChatMessageRecord方法就可以,仅仅是在构造ChatMessageRecord对象时,字段的赋值有所差别。

(2)使用DataRabbit实现该接口时(如ChatRecordPersister类),通过属性DataBaseType来控制訪问的是否为Sqlite数据库。然后在服务端使用ChatRecordPersister存取聊天记录时,就将DataBaseType设置为SqlServer;client则设置为Sqlite。

三.可能的Remoting的接口

  当我们从server载入聊天记录时,能够考虑使用Remoting技术来实现,假设是这样,仅仅须要在服务端把IChatRecordPersister接口暴露为Remoting服务。然后client使用这一Remoting服务进行聊天记录查询。这样一来,client在切换从本地载入和从server载入时。仅仅须要切换IChatRecordPersister为本地ChatRecordPersister对象的引用或remoting远程引用就可以。

整个的代码实现将会很简洁一致。

  到这里,关于聊天记录模块的设计与实现就介绍得差点儿相同了,按照这种思路,大家在自己的IM系统中添加聊天记录的功能应该是非常easy的了。

最后。上一张OrayTalkclient查询聊天记录界面的截图:

 就到这里了。还有疑问的朋友。请给我留言,我会及时回复的。

版权声明:本文博主原创文章,博客,未经同意不得转载。

IM设计与实现的系统模块的聊天记录的更多相关文章

  1. Java开源生鲜电商平台-财务系统模块的设计与架构(源码可下载)

    Java开源生鲜电商平台-财务系统模块的设计与架构(源码可下载) 前言:任何一个平台也好,系统也好,挣钱养活团队这个是无可厚非的,那么对于一个生鲜B2B平台盈利模式( 查看:http://www.cn ...

  2. Python—day17时间模块、系统模块、递推遍历、序列化

    一.time'''时间戳(timestamp):time.time()延迟线程的运行:time.sleep(secs)(指定时间戳下的)当前时区时间:time.localtime([secs])(指定 ...

  3. C语言课程设计——电影院订票系统

    1. 课题简介 大家都爱看电影,现请参考一个熟悉电影票预订系统,实现C语言版的订票系统.了解订票如何实现的.系统主要有2类用户:管理员用户和顾客用户. 管理员用户登录系统后,实现电影放映厅信息管理和电 ...

  4. Atitit.收银系统模块架构attilax 总结

    Atitit.收银系统模块架构attilax 总结 1. 常规收银系统模块结构1 1.1. 商品管理1 1.2. 会员系统1 1.3. 报表系统1 1.4. 会员卡系统1 1.5. 库存管理1 2.  ...

  5. Qsys配置生成nios系统模块

    1. 本次使用的是别人写好的例程,主要研究学习,使用quartus 11打开工程 2. bdf文件是块编辑器的,相当于原理图,以前只在用NIOS的时候会用到这种方式.接下来新建一个工程,添加原理图元件 ...

  6. 设计自用的golang日志模块

    设计自用的golang日志模块 golang的原生日志模块不能满足需求,而开源的第三方包,也不完全够用.用户较多的logrus,却没有rotate功能,这已经是众所周知的.对于运维来说,当然是希望日志 ...

  7. Java高级项目实战02:客户关系管理系统CRM系统模块分析与介绍

    本文承接上一篇:Java高级项目实战之CRM系统01:CRM系统概念和分类.企业项目开发流程 先来CRM系统结构图: 每个模块作用介绍如下: 1.营销管理 营销机会管理:针对企业中客户的质询需求所建立 ...

  8. 基于ZooKeeper,Spring设计实现的参数系统

    一.简介 基于ZooKeeper服务端.ZooKeeper Java客户端以及Spring框架设计的用于系统内部进行参数维护的系统. 二.设计背景 在我们日常开发的系统内部,开发过程中最常见的一项工作 ...

  9. 基于STM32+华为云IOT设计智能称重系统

    摘要:选择部署多个重量传感器和必要的算法.通过WiFi 通信模块.GPS定位模块,采集车辆称重数据一地理位置信息,并通过网络发送至云平台,设计图形化UI界面展示称重.地图位置等重要信息,实现对称重系统 ...

随机推荐

  1. POJ 1160 Post Office (动态规划)

    Post Office Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 15412   Accepted: 8351 Desc ...

  2. Delphi 数据类型列表 good

    Delphi 数据类型列表 分类 范围 字节 备注 简单类型 序数 整数 Integer -2147483648 .. 2147483647 4 有符号32位 Cardinal 0 .. 429496 ...

  3. ASP.NET常被忽视的一些细节

    原文:ASP.NET常被忽视的一些细节 前段时间碰到一个问题:为什么在ASP.NET程序中定时器有时候会不工作? 这个问题看起来很奇怪,代码好像也没错,但就是结果与预期不一致. 其实这里是ASP.NE ...

  4. operator= 复制操作符的意外

    首先,看以下的代码的输出时什么: 上述代码做了最理所当然的事.就是将Derived的两个对象进行了交换.可是通过指针进行的赋值输出却不是预期的: 居然调用的是Base的operator=,也就意味着我 ...

  5. ie浏览器提交参数和其它浏览器的区别

    场景描述: 用户注册模块(ajax提交方式,post方法),在url后追加了一个参数,如:url+‘btnvalue=中文参数’,如此在非ie浏览器注册时,功能完好,但在ie下注册不成功.调式后发现在 ...

  6. Android中关于JNI 的学习(六)JNI中注冊方法的实现

    在前面的样例中,我们会发现,当在Java类中定义一个方法的时候,例如以下: public class ParamTransferTest { public static int testval = 1 ...

  7. 沙朗javascript总结一下(一)---基础知识

    我也听说过Javascript这东西.我一直感觉很神奇,但它并没有去太懂.今天,牛腩哥哥随后的初步研究,一些浅显的认识.就先总结一下. 首先,什么是javascript? javascript是一种直 ...

  8. 黑马程序员:Java基础总结----类加载器

    黑马程序员:Java基础总结 类加载器   ASP.Net+Android+IO开发 . .Net培训 .期待与您交流! 类加载器 Java虚拟机中可以安装多个类加载器,系统默认三个主要类加载器,每个 ...

  9. Android开发周报:Flyme OS开源、经典开源项目解析

    Android开发周报:Flyme OS开源.经典开源项目解析 新闻 <魅族Flyme OS源码上线Github> :近日魅族正式发布了MX5,并且在发布会上,魅族还宣布Flyme OS开 ...

  10. C++技术问题总结-第11篇 网络通信中主机序网络序

    网络通信常常涉及到字节序转化,接下来理解主机序和网络序有什么异同. ①主机字节顺序HBO(Host Byte Order) 採用小头序(little-endian),从低到高的顺序存储. 低位字节排放 ...