上次的探讨没有任何结果,我浏览了大量的文章和个别系统的参考!决定用Cache来做,这可能有点难以接受但是配合mvc过滤器来做效果非常好!
由于之前的过滤器我们用过了OnActionExecuting这个方法来判断权限
现在在方法被执行后我们用OnActionExecuted来监听用户的操作和刷新用户在线列表
首先下载这个类库,代码清晰,并加注释
这个类库包括了操作在线用户列表的增删方法,大家可以下载下来看并放到
可以打开研究其代码!
在App.Admin新建类OnlineHttpModule
using App.Core.OnlineStat;using App.Models.Sys;using System;using System.Collections.Generic;using System.Globalization;using System.Linq;using System.Net.Http;using System.Text;using System.Threading;using System.Threading.Tasks;using System.Web;using System.Web.Routing;namespace App.Admin{ public class OnlineHttpModule { // 缓存键 public static readonly string g_onlineUserRecorderCacheKey = "__OnlineUserRecorder"; #region IHttpHandler 成员 public static void ProcessRequest() { // 获取在线用户记录器 OnlineUserRecorder recorder = HttpContext.Current.Cache[g_onlineUserRecorderCacheKey] as OnlineUserRecorder; if (recorder == null) { // 创建记录器工厂 OnlineUserRecorderFactory factory = new OnlineUserRecorderFactory(); // 设置用户超时时间 factory.UserTimeOutMinute = 2; // 统计时间间隔 factory.StatisticEventInterval = 20; // 创建记录器 recorder = factory.Create(); // 缓存记录器 HttpContext.Current.Cache.Insert(g_onlineUserRecorderCacheKey, recorder); } OnlineUser user = new OnlineUser(); AccountModel model = (AccountModel)HttpContext.Current.Session["Account"];//注意session的名称是和登录保存的名称一致 // 用户名称 user.UserName = Convert.ToString(model.Id); // SessionID user.SessionID = HttpContext.Current.Session.SessionID; // IP 地址 user.ClientIP = HttpContext.Current.Request.UserHostAddress; // 最后活动时间 user.ActiveTime = DateTime.Now; // 最后请求地址 user.RequestURL = HttpContext.Current.Request.RawUrl; // 保存用户信息 recorder.Persist(user); } #endregion }}
这个类在用户登录时被调用和在过滤器被调用,调用代码
过滤器:
public class SupportFilterAttribute : ActionFilterAttribute { public string ActionName { get; set; } private string Area; // 方法被执行后的更新在线用户列表 public override void OnActionExecuted(ActionExecutedContext filterContext) { OnlineHttpModule.ProcessRequest(); }......................................
登录时候的设置:
AccountModel account = new AccountModel(); account.Id = user.Id; account.TrueName = user.TrueName; account.Photo = string.IsNullOrEmpty(user.Photo)?"/Images/Photo.jpg":user.Photo; Session["Account"] = account; //在线用户统计 OnlineHttpModule.ProcessRequest();
调用非常简单,实现非常简单!
现在看看如果获取在线列表:
// 绑定在线用户列表 IListuserList = recorder.GetUserList(); foreach (var OnlineUser in userList) { sb.AppendFormat(OnlineUser.UserName+" "); }
OnlineHttpModule可以自由设置统计的间隔(秒),和用户超时的时间,这很精准的统计了用户2分钟无操作被视为离线!
我分别用IE和chome测试了2个用户,同时也关闭浏览器测试用户,准确性也不错!抛弃了不准确的原始老方法