WhoIsOnline ;) - 解读CNForum源码中在线用户统计

简介:
原文: http://www.cnblogs.com/andrewbao/archive/2005/01/05/87061.html




下载CnForumsBeta1(今天发现CnForum1.2测试版本已经发布,可以至开发实验室下载,或者访问宝玉的blog)已经有段时间,一直想看看其中的代码,但是它的项目结构实在是复杂(也是本人能力有限),实在是觉得无从下手。
最近由于项目的原因对如何统计在线用户信息很感兴趣,正好利用这个机会学习一下CnForum的实现方式。
 
BTW:用Google搜了一下“asp.net 用户统计”(如google搜索结果),结果发现前几篇文章的内容几乎相同,只是稍微修改了某些字和出处而已,只是有意思。看样子真是天下文章一大“抄”啊!当然这不是今天讨论的重点,下面切入主题。

首先就是选取切入点。在安装CnForum后的论坛首页左下方有用户在线信息的统计,显示效果如图:

当用户点击“用户在线信息”时,将弹出显示详细的用户在线信息。查看“用户在线信息”链接发现是指向ViewOnline.aspx的。那么就从ViewOnline.aspx页面开始着手吧。
查看ViewOnline.aspx页面的HTML代码,发现主要功能实现是AspNetForums.Controls下的WhoIsOnlineView控件展现的。
进一步查看WhoIsOnlineView控件代码(在子项目Controls下)。
WhoIsOnlineView类是继承SkinnedForumWebControl类的,从名称来看SkinnedForumWebControl类应该不是重点。重点是WhoIsOnlineView类中重写的InitializeSkin(Control skin)方法。从方法中的代码知道是使用repeat控件来显示注册会员和游客信息。
由于获取注册会员和游客信息的方法应该是雷同的,所以这里只需要分析在线注册会员的获得即可。
从代码 repeater.DataSource = Users.GetUsersOnline(15);知道在线注册会员数据的获得是通过Users类的GetUsersOnline(int pastMinutes)方法得到。
定位到Users类(子项目Components下)的GetUsersOnline方法,进而发现实际是调用Users类的GetMembersGuestsOnline(int pastMinutes)方法获得数据。
检查GetMembersGuestsOnline方法的函数体,其中对获取在线注册会员数据的关键代码应该是:
    ForumsDataProvider dp = ForumsDataProvider.Instance();

    users = dp.WhoIsOnline(pastMinutes);



分析ForumsDataProvider dp = ForumsDataProvider.Instance()
定位至ForumsDataProvider类(子项目Components中Provider下)的静态方法Instance()->静态方法Instance (HttpContext context, string providerTypeName, string databaseOwner, string connectionString),目的是返回一个ForumsDataProvider类的实例。
那么ForumsDataProvider的Instance方法到底完成了什么呢?
首先通过ForumConfiguration config = ForumConfiguration.GetConfig();获得ForumConfirguration类的对象。定位至ForumConfirguration的GetConfig方法。

奇怪的事情出现了:GetConfig方法中只有简单的一句(ForumConfiguration) ConfigurationSettings.GetConfig("forums/forums"),但是从ForumConfirguration类定义来看私有成员有很多(如providers、defaultProvider等),而且回头看看
ForumsDataProvider的Instance方法中在调用GetConfig方法后就使用了config的providers。那这些私有成员到底是怎样初始化的呢?看样子玄机就在ConfigurationSettings.GetConfig方法上。查看MSDN知道这个方法是用来“返回用户定义的配置节的配置设置”,查看Web.config的配置,发现forums/forums节是<section name="forums" type="AspNetForums.Configuration.ForumsConfigurationHandler, AspNetForums.Components" />。
在MSDN中搜索section,有这样一段话“声明配置节实质上为配置文件定义了新元素。新元素包含配置节处理程序(即实现 IConfigurationSectionHandler 接口 的类)读取的设置。所定义的节的属性和子元素取决于用来读取设置的节处理程序。”。难道说ForumsConfigurationHandler是指项目中自定义的配置节处理程序。
搜索项目,果然在ForumConfiguration.cs文件(子项目Components/Confirguration下)找到了类ForumsConfigurationHandler,它实现了接口IConfigurationSectionHandler。搜索MSDN知道IConfigurationSectionHandler接口有方法Create,可以返回用户自己的配置对象。
回到代码中,在ForumsConfigurationHandler中用户获得了ForumConfiguration对象,并且通过方法LoadValuesFromConfigurationXml初始化了ForumConfiguration对象的私有成员。
哦,原来如此!看似简单的一句return (ForumConfiguration) ConfigurationSettings.GetConfig("forums/forums")其实已经填充了所需的配置内容。
[是不是很罗嗦啊 ,不要拿砖头砸我哦!喝口水先~~~ ]

回到ForumsDataProvider类的Instance方法中,随后的代码就是获得缺省配置内容(详细情况可以查看Web.config),包括数据库连接字符串、数据库Owner等配置信息,以及 关键的缺省Provider类型名称providerTypeName,在我的项目配置中是“AspNetForums.Data.SqlDataProvider”,记住这个名字,它随后将起到关键作用!
继续>>根据代码,当Cache["DataProvider"]为null时,获得与前面得到的providerTypeName相应的Type,下面有这样一句代码:cache.Insert( "DataProvider", type.GetConstructor(paramTypes) );。
问题来了,这段代码是做什么的呢?
搜索MSDN知道Type.GetConstructor 方法是“获取当前Type的特定构造函数”(这里说的特定就是指paramTypes,即有两个string参数的构造函数)。根据前面知道type的类型是AspNetForums.Data.SqlDataProvider,那就意味着应该有个类,名字是SqlDataProvider,并且有个样子是SqlDataProvider(string param1,string param2)的构造函数。
搜索项目...果然在子项目SqlDataProvider下的有个名为SqlDataProvider的类,并且构造函数为SqlDataProvider(string databaseOwner, string connectionString)。 原来cache.Insert( "DataProvider", type.GetConstructor(paramTypes) )是把与WebConfig中配置的defaultProvider(这里是SqlDataProiver,继承ForumsDataProvider)相应的ConstructorInfo,通过这个ConstructInfo对象我们可以调用SqlDataProvider的构造函数来获得SqlDataProvider对象。
这样做的好处是显而易见的,我们只需要修改Web.config就可以灵活的修改具体访问数据所使用的类。

然后通过ConstructorInfo的Invoke方法获得了SqlDataProvider对象。
    object[] paramArray = new object[2];
    paramArray[0] = databaseOwner;
    paramArray[1] = connectionString;

    return (ForumsDataProvider)(  ((ConstructorInfo)cache["DataProvider"]).Invoke(paramArray) );

至此,通过ForumsDataProvider dp = ForumsDataProvider.Instance()实际获得了SqlDataProvider对象,而在SqlDataProvider类中通过重写实现了ForumsDataProvider中定义的所有abstract方法,即实现了所有需要的数据访问方法。


分析users = dp.WhoIsOnline(pastMinutes)
既然访问数据的对象已经准备完毕了,users = dp.WhoIsOnline(pastMinutes)也就变成了仅仅是调用SqlDataProvider对象的方法而已了。
找到SqlDataProvider类的WhoIsOnline方法,即public override Hashtable WhoIsOnline(int pastMinutes)
这个方法其实就是调用存储过程forums_Users_Online,查看这个存储过程(这个存储过程有输入参数@PastMinutes,此处值为15)。
发现它首先会删除最近一个小时都没有Activity(活动)的在线用户信息,即:
    DELETE
        forums_UsersOnline
    WHERE
    LastActivity < DateAdd(hour, -1, GetDate())
然后根据表forums_UsersOnline中的数据找出最近15分钟有Activity(活动)注册会员信息,以及从表forums_AnonymousUsers中找出所有在线游客信息。



OK,对CnForum中在线用户信息统计的实现方式就分析到这里。
感言:阅读高手的代码的确是收益匪浅,写这个Post也希望能够起到抛砖引玉的效果,共同进步吧~


在分析的过程中难免有错误的地方,请见谅。 当然也欢迎大家扔砖..


本文转自浪子博客园博客,原文链接:http://www.cnblogs.com/walkingboy/archive/2005/04/14/137758.html,如需转载请自行联系原作者

目录
相关文章
|
4月前
用二维码收集信息时,在后台可以查看、统计哪些数据?
如果是用草料二维码平台搭建的二维码,前往后台,在表单列表中找到对应的表单,就能查看数据了,包括通过该表单收集到的所有明细数据、基于关联二维码的统计数据、填写该表单的填表人统计数据、基于表单组件的字段统计数据。
用二维码收集信息时,在后台可以查看、统计哪些数据?
|
4月前
|
存储 前端开发 NoSQL
如何优雅地实现在线人数统计功能:技术干货分享
在现代Web开发中,实时在线人数统计是一个常见且重要的功能,它不仅提升了用户体验,还能为网站运营者提供宝贵的数据支持。今天,我们将深入探讨如何优雅地实现这一功能,结合前端展示、后端处理及数据存储等多个方面,为您呈现一套完整的技术解决方案。
421 5
|
3月前
|
数据采集
以“股票代码实时抓取股票信息”为例的爬虫案例
爬虫—根据股票代码实时抓取股票信息
127 0
|
8月前
|
存储 移动开发 小程序
利用微搭搭建信息查询小程序
利用微搭搭建信息查询小程序
|
存储
统计网站的在线人数
统计网站的在线人数
108 0
|
缓存 运维 前端开发
如何设计一个70W在线人数的弹幕系统文章分析
如何设计一个70W在线人数的弹幕系统文章分析
97 3
|
前端开发 JavaScript 网络协议
分析“如何设计一个 70w 在线人数的弹幕系统”
分析“如何设计一个 70w 在线人数的弹幕系统”
107 0
|
JSON 关系型数据库 大数据
电商项目之用户行为日志字段分析|学习笔记
快速学习电商项目之用户行为日志字段分析
|
监控 安全 Java
CAS在线用户统计实现
随着应用平台的不断发展,对统一认证的能力需求越来越广泛。CAS框架在交付项目中承载了所有应用的登录能力,对平台用户登录状态统一管理。为了满足平台监控、日志等方面对用户实时在线情况展示的需求,需要在CAS server端开放rest api,实现用户在线数据统计。
|
Oracle 关系型数据库 Shell
[自制工具]批量后台更新统计信息
Oracle数据库有时需要批量收集数据库的统计信息,如在大量数据迁移或大量数据更新以后,但是收集的时间可能会较长,为了避免网络中断等意外情况可能引起的麻烦,今天调试了这个小脚本,可以分用户批量执行,同时记录执行时间等日志信息,比较实用。
223 0