asp.net 访问页面访问统计实现
0x00、背景:
1、用户访问网站所有页面就将访问统计数加1 ,按每月存放。
2、站点并没有用到母版面来实现,所有各个页面都很独立。
3、网站是很早这前的网站,尽量省改动以前的代码。按理说我们应该做一个第三方统计来处理会更好,
但应客户要求还要弄到一个站点下!实际情况是尽量小改页面就好!
4、IIs7的服务器请参考 《asp.net 访问页面访问统计实现 for iis7》
0x01、核心代码:
1、实现Http拦截操作,核心代码就是这一个了:
using System; using System.Collections.Generic; using System.Collections.Specialized; using System.Configuration; using System.Diagnostics; using System.IO; using System.Linq; using System.Web; using System.Xml; namespace HYSWare.Web { public class CurVisitCount { public DateTime BeginTime{get;set;} public int Count { get; set; } } public class RequestHandler : IHttpModule { private static System.Timers.Timer timer1; private static System.Web.Caching.Cache _Cache; private int _IntervalMinute; public int IntervalMinute { get { string _IntervalMinuteStr = ConfigurationManager.AppSettings["IntervalMinute"]; if (string.IsNullOrEmpty(_IntervalMinuteStr)) { _IntervalMinute = 5; } else { _IntervalMinute = Convert.ToInt32(_IntervalMinuteStr); } return _IntervalMinute; } } public RequestHandler() { if (_Cache == null) { _Cache = new System.Web.Caching.Cache(); } if (timer1 == null) { timer1 = new System.Timers.Timer(); timer1.Interval = IntervalMinute * 60000; timer1.Elapsed += new System.Timers.ElapsedEventHandler(timer1_Tick); timer1.AutoReset = true;//设置是执行一次(false)还是一直执行(true); timer1.Enabled = true;//是否执行System.Timers.Timer.Elapsed事件; } if(_Cache["CurVisitCount"]==null) _Cache["CurVisitCount"] = new CurVisitCount { BeginTime = DateTime.Now, Count = 0 }; if(_Cache["VisitCount"]==null) _Cache["VisitCount"] = "0"; } void IHttpModule.Dispose() { } void IHttpModule.Init(HttpApplication context) { context.BeginRequest += new EventHandler(context_BeginRequest); //context.EndRequest += new EventHandler(context_EndRequest); } void context_BeginRequest(object sender, EventArgs e) { string[] requestEx = { ".aspx",".htm", ".html"}; HttpApplication application = (HttpApplication)sender; var curRequest = application.Context.Request; if (requestEx.Contains(curRequest.CurrentExecutionFilePathExtension)) { if (_Cache["CurVisitCount"] == null) _Cache["CurVisitCount"]=new CurVisitCount { BeginTime = DateTime.Now, Count = 1 }; CurVisitCount curVisitCount = (CurVisitCount)_Cache["CurVisitCount"]; if (curVisitCount.BeginTime.Year + curVisitCount.BeginTime.Month < DateTime.Now.Year + DateTime.Now.Month) { UpdateVisitCount(curVisitCount.BeginTime); curVisitCount = (CurVisitCount)_Cache["CurVisitCount"]; } curVisitCount.Count += 1; _Cache["CurVisitCount"] = curVisitCount; if (_Cache["VisitCountXml"] == null) _Cache["VisitCountXml"] = GetVisitCountInXml(); int visitCountXml = 0; int.TryParse(_Cache["VisitCountXml"].ToString(),out visitCountXml); _Cache["VisitCount"] = (visitCountXml + curVisitCount.Count).ToString(); } //application.Context.Response.Write("自定义ModuleRequest开始"); } private int GetVisitCountInXml() { int ret = 0; string _VisitPath = AppDomain.CurrentDomain.BaseDirectory + "App_Data\\Xml\\VisitCountData.xml"; XmlDocument doc = new XmlDocument(); if (File.Exists(_VisitPath)) { doc.Load(_VisitPath); var curNode = doc.SelectNodes("//Visit"); foreach (XmlNode m in curNode) { var countAttr = m.Attributes.GetNamedItem("VCount"); int v = 0; int.TryParse(countAttr.Value, out v); ret += v; } } return ret; } private void UpdateVisitCount(DateTime time) { if (_Cache["CurVisitCount"] == null) _Cache["CurVisitCount"]= new CurVisitCount { BeginTime = DateTime.Now, Count = 0 }; CurVisitCount curVisitCount = (CurVisitCount)_Cache["CurVisitCount"]; if (curVisitCount.Count > 0) { string _VisitPath = AppDomain.CurrentDomain.BaseDirectory + "App_Data\\Xml\\VisitCountData.xml"; XmlDocument doc = new XmlDocument(); if (File.Exists(_VisitPath)) { doc.Load(_VisitPath); var curNode = doc.SelectSingleNode(string.Format("//Visit[@Year='{0}' and @Month='{1}']", time.Year, time.Month)); if (curNode != null) { var countAttr = curNode.Attributes.GetNamedItem("VCount"); int count = 0; int.TryParse(countAttr.Value, out count); countAttr.Value = (count + curVisitCount.Count).ToString(); } else { //有文件但没有本月数据 XmlNode root = doc.SelectSingleNode("Visits"); XmlElement element1 = doc.CreateElement("Visit"); element1.SetAttribute("Year", time.Year.ToString()); element1.SetAttribute("Month", time.Month.ToString()); element1.SetAttribute("VCount", curVisitCount.Count.ToString()); root.AppendChild(element1); } } else { XmlDeclaration dec = doc.CreateXmlDeclaration("1.0", "utf-8", null); doc.AppendChild(dec); //创建一个根节点(一级) XmlElement root = doc.CreateElement("Visits"); doc.AppendChild(root); //创建节点(二级) XmlElement element1 = doc.CreateElement("Visit"); element1.SetAttribute("Year", time.Year.ToString()); element1.SetAttribute("Month", time.Month.ToString()); element1.SetAttribute("VCount", curVisitCount.ToString()); root.AppendChild(element1); } doc.Save(_VisitPath); _Cache["VisitCountXml"] = GetVisitCountInXml(); _Cache["VisitCount"] = _Cache["VisitCountXml"]; _Cache["CurVisitCount"] = new CurVisitCount { BeginTime = DateTime.Now, Count = 0 }; } } private void timer1_Tick(object sender, EventArgs e) { UpdateVisitCount(DateTime.Now); } } }
2、web.config中添加配置
<!-- 有关如何配置 ASP.NET 应用程序的详细信息,请访问 http://go.microsoft.com/fwlink/?LinkId=169433 --> <configuration> <appSettings>
...... <!--设置更新访问统计Xml,间隔时间(分钟)默认为5分钟--> <add key="IntervalMinute" value="5"/> </appSettings> ....... <system.webServer> <modules runAllManagedModulesForAllRequests="true"> <add name="customerModule" type="HYSWare.Web.RequestHandler, HYSWare.Web"/> </modules> ...... </system.webServer> </configuration>
3、存放数据的XML文件
<?xml version="1.0" encoding="utf-8"?> <Visits> <Visit Year="2017" Month="8" VCount="92" /> <Visit Year="2017" Month="7" VCount="13000000" /> </Visits>
4、取得缓存的的访问数据 VisitCountHandler.ashx,VisitCountHandler.ashxcs
using System; using System.Collections.Generic; using System.Linq; using System.Web; namespace HYSWare.Web { /// <summary> /// VisitCountHandler 的摘要说明 /// </summary> public class VisitCountHandler : IHttpHandler { private static System.Web.Caching.Cache _Cache; public VisitCountHandler() { if (_Cache == null) { _Cache = new System.Web.Caching.Cache(); } } public void ProcessRequest(HttpContext context) { context.Response.ContentType = "text/plain"; if (_Cache["VisitCount"] == null) _Cache["VisitCount"] = "0"; context.Response.Write(_Cache["VisitCount"].ToString()); } public bool IsReusable { get { return false; } } } }
5、调用取访问统计数据的有js代码
var visitCount = 0; $.ajax({ type: "Post", url: "VisitCountHandler.ashx", data: "{}", async: false, contentType: "application/json; charset=utf-8", dataType: "json", success: function (data) { visitCount = data; }, error: function (err) { alert(err); } });
0x02、总结:
主要还是觉得缓存使用感觉有点不对的样子,也许有更好的方法!
还有觉得拦截方法也是挻好用的!