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、总结:

主要还是觉得缓存使用感觉有点不对的样子,也许有更好的方法!

还有觉得拦截方法也是挻好用的!