利用HttpHandler和Cache统计点击量

  因为访问量大,做页面浏览量的时候不能直接操作库;用文件来记录的话,虽然减缓了数据库的压力但是对服务器I/O却是一个考验;而缓存正是.Net的一大优势,所以想出HttpHandler结合Cache来减缓I/O操作,这样I/O跟数据库的压力都解决了!

首先创建统计类库

1.创建CounterHelper统计类
  1using System;
  2using System.Web;
  3using System.Web.Caching;
  4using System.Collections.Specialized;
  5using System.Data;
  6using System.Data.SqlClient;
  7using System.Configuration;
  8using System.Text;
  9using System.IO;
 10
 11namespace MYSpace.Counter
 12{
 13    /// <summary>
 14    /// Counter 的摘要说明。
 15    /// </summary>

 16    public class CounterHelper
 17    {
 18        private  int _Hits = 0//累计的点击数
 19        private string _FileName = "";
 20        private string FilePth = string.Empty;
 21        private string ErrorLogFilePth = string.Empty;
 22        private   int[] HitsArr = {-1,0,0}//HitsArr[0]表示总的点击数HitsArr标识昨天的点击数HitsArr表示今天的点击数
 23        CacheItemRemovedCallback onRemove = null;//CacheItemRemovedCallback对象
 24        private  string CacheName = "UpdateHitsForExpired";//缓存名称
 25        private object LockForAddHits = new object();//LockForAddHits锁
 26        private object LockForItemRemovedFromCacheHits = new object();//ItemRemovedFromCacheHits锁
 27
 28        /// <summary>
 29        /// 构造函数
 30        /// </summary>

 31        public CounterHelper(string filename)
 32        {
 33            _FileName = filename;
 34            CacheName = filename;
 35            HttpContext ctx = HttpContext.Current;
 36            FilePth = ctx.Server.MapPath("~/" + _FileName + ".txt");
 37            ErrorLogFilePth = ctx.Server.MapPath("~/" + _FileName + ".txt");
 38            LoadHits();
 39        }

 40
 41        /// <summary>
 42        /// 将累计点击数保存到全局变量,当它达到一定量时保存到文本文件,并清空
 43        /// </summary>

 44        public  void AddHits()
 45        {
 46            lock(LockForAddHits)
 47            {
 48                if( Hits != 0 )
 49                {
 50                    Add();
 51                    if(Hits > 200 )
 52                    {
 53                        //--移除                        
 54                        HttpRuntime.Cache.Remove(CacheName);
 55                    }

 56                }

 57                else
 58                {
 59                    onRemove = new CacheItemRemovedCallback(ItemRemovedFromCache);
 60                    HttpRuntime.Cache.Insert(
 61                        CacheName,
 62                        "This Object For Expired"
 63                        null,
 64                        DateTime.Now.AddSeconds(5) ,
 65                        TimeSpan.Zero,
 66                        System.Web.Caching.CacheItemPriority.Normal,
 67                        onRemove
 68                        );
 69                    Add();                    
 70                }

 71            }

 72        }
            
 73
 74        /// <summary>
 75        /// 保存到文本文件
 76        /// </summary>
 77        /// <param name="AllId"></param>

 78        private  void SaveHitsToFile(int hits)
 79        {
 80            string hitsinfo = string.Empty;            
 81
 82            DateTime LastWriteTime = File.GetLastWriteTime(FilePth);
 83            if((DateTime.Today - LastWriteTime).TotalDays >0 )
 84            {
 85                //--表示今天第一次写数据
 86                HitsArr[1= HitsArr[2];//--将当前累计的点击数赋给昨天的点击数
 87                HitsArr[2= hits;//--设置今天的点击数
 88                using(StreamWriter streamWriter = new StreamWriter(FilePth,false) )
 89                {
 90                    streamWriter.Write(string.Format("{0},{1},{2}",HitsArr[0+ hits,HitsArr[1] ,hits));
 91                    streamWriter.Flush();
 92                }

 93            }

 94            else
 95            {
 96                using(StreamWriter streamWriter = new StreamWriter(FilePth,false) )
 97                {
 98                    streamWriter.Write(string.Format("{0},{1},{2}",HitsArr[0+ hits,HitsArr[1],HitsArr[2+ hits));
 99                    streamWriter.Flush();
100                }

101            }

102        }
    
103        
104        /// <summary>
105        /// 当缓存被移除或过期是触发的回调事件
106        /// </summary>
107        /// <param name="key"></param>
108        /// <param name="value"></param>
109        /// <param name="reason"></param>

110        private  void ItemRemovedFromCache(string key, object value,CacheItemRemovedReason reason)
111        {
112            try
113            {
114                清空并写到文本文件
132            }

133            catch(Exception ex)
134            {
135                using(StreamWriter streamWriter = new StreamWriter(ErrorLogFilePth,false) )
136                {
137                    streamWriter.Write(string.Format("时间:{0}\r\n描述信息:{1}\r\n",DateTime.Now,ex.Message));
138                    streamWriter.Flush();
139                }

140            }

141        }

142
143        /// <summary>
144        /// 获取所有的点击数
145        /// </summary>

146        public int AllHits
147        {
148            get
149            {
150                return HitsArr[0+ Hits;
151            }

152        }

153
154        /// <summary>
155        /// 获取昨天点击数
156        /// </summary>

157        public  int YesterdayHits
158        {
159            get
160            {
161                return HitsArr[1];
162            }

163        }
    
164
165        /// <summary>
166        /// 获取今天点击数
167        /// </summary>

168        public  int TodayHits
169        {
170            get
171            {
172                return HitsArr[2+ Hits;
173            }

174        }

175
176        /// <summary>
177        /// 加载点击数
178        /// </summary>

179        private  void LoadHits()
180        {
181            if (HttpRuntime.Cache[CacheName] == null)
182            {
183                HttpContext ctx = HttpContext.Current;
184                if (!File.Exists(FilePth))
185                {
186                    //--第一次使用
187                    using (StreamWriter streamWriter = new StreamWriter(FilePth))
188                    {
189                        streamWriter.Write(string.Format("{0},{1},{2}"000));
190                        streamWriter.Flush();
191                    }

192                    HitsArr[0= 0;
193                    HitsArr[1= 0;
194                    HitsArr[2= 0;
195                }

196                else
197                {
198                    string hitsinfo = string.Empty;
199                    using (StreamReader objStreamReader = new StreamReader(FilePth))
200                    {
201                        hitsinfo = objStreamReader.ReadLine();
202                    }

203                    if (hitsinfo != "")
204                    {
205                        string[] arr = hitsinfo.Split(',');
206                        HitsArr[0= Convert.ToInt32(arr[0]);//全部
207                        HitsArr[1= Convert.ToInt32(arr[1]);//昨天
208                        HitsArr[2= Convert.ToInt32(arr[2]);//今天
209                    }

210                    else
211                    {
212                        HitsArr[0= 0;
213                        HitsArr[1= 0;
214                        HitsArr[2= 0;
215                    }

216                }

217                HttpRuntime.Cache["b" + CacheName] = HitsArr;
218            }

219            else
220            {
221                HitsArr = (int[])HttpRuntime.Cache["b" + CacheName];
222                //HitsArr[0] += 1;
223                //HitsArr[2] += 1;
224
225            }

226        }

227
228
229        /// <summary>
230        /// 获取累计的点击数
231        /// </summary>

232        private  int Hits
233        {
234            get
235            {
236                return    _Hits;
237            }

238            set
239            {
240                _Hits = value;
241            }

242        }

243
244        /// <summary>
245        /// 累加
246        /// </summary>
247        /// <param name="id"></param>

248        private  void Add()
249        {
250            if(HitsArr[2]<14000)
251            {
252                //_Hits = _Hits + new Random(DateTime.Now.Second).Next(60,80);
253                _Hits = _Hits + 1;
254            }

255            else
256            {
257                _Hits = _Hits + 1;//_Hits = _Hits + new Random(DateTime.Now.Second).Next(2,8); 传回指定范围的随机数
258            }

259        }

260        /// <summary>
261        /// 文件名
262        /// </summary>
263        
264        /// <summary>
265        /// 获取文件名
266        /// </summary>

267        public string FileName
268        {
269            get return _FileName; }
270            set { _FileName = value; }
271        }

272    }

273}

274

2.创建HttpHandler
 1using System;
 2using System.Web;
 3using System.Text.RegularExpressions;
 4
 5namespace MYSpace.Counter
 6{
 7    /// <summary>
 8    /// HitsHandler 的摘要说明。
 9    /// </summary>

10    public class CounterHandler: IHttpHandler
11    {
12        public void ProcessRequest(HttpContext ctx) 
13        {
14            CounterHelper objCounterHelper = new CounterHelper(ctx.Request.QueryString["id"].ToString());
15            objCounterHelper.AddHits();
16            ctx.Response.Write(string.Format("document.write('页面访问量:{0} 昨日:{1} 今日:{2}  id :{3}')",objCounterHelper.AllHits,objCounterHelper.YesterdayHits,objCounterHelper.TodayHits,ctx.Request.Url.AbsoluteUri));
17        }

18
19        public bool IsReusable 
20        {
21            get return false; }  
22        }

23    }

24}

25

生成dll后创建一个Website,然后把dll引用进来!
接着在web.config里面添加配置:
    <httpHandlers>
      <add verb="*" path="count.aspx" type="MYSpace.Counter.CounterHandler,MYSpace.Counter" />
    </httpHandlers>


最后在web页面调用就ok了。页面代码如下:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<html xmlns="http://www.w3.org/1999/xhtml" >
<head runat="server">
    <title>无标题页</title>
    <SCRIPT LANGUAGE="JavaScript" src='count.aspx?id=o4'></SCRIPT>
</head>
<body>
    <form id="form1" runat="server">
    <div>
   
    </div>
    </form>
</body>
</html>
很简单吧,这里只介绍到写入文件,如果想写入库里面,直接读取文件里的数值就搞定!

posted @ 2009-06-30 08:52  PointNet  阅读(1011)  评论(1编辑  收藏  举报