明天的明天 永远的永远 未知的一切 我与你一起承担 ??

是非成败转头空 青山依旧在 几度夕阳红 。。。
  博客园  :: 首页  :: 管理

利用HttpHandler和Cache统计点击量 {转}

Posted on 2012-07-08 21:38  且行且思  阅读(451)  评论(0编辑  收藏  举报

来源: http://www.cnblogs.com/keepsilence/archive/2009/07/23/1529199.html

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

首先创建统计类库

1.创建CounterHelper统计类

using System;
using System.Web;
using System.Web.Caching;
using System.Collections.Specialized;
using System.Data;
using System.Data.SqlClient;
using System.Configuration;
using System.Text;
using System.IO;

namespace MYSpace.Counter

{
/// <summary>
/// Counter 的摘要说明。
/// </summary>
    public class CounterHelper
    {
       private  int _Hits = 0; //累计的点击数
       private string _FileName = "";
       private string FilePth = string.Empty;
       private string ErrorLogFilePth = string.Empty;
       private   int[] HitsArr = {-1,0,0}; //HitsArr[0]表示总的点击数HitsArr标识昨天的点击数HitsArr表示今天的点击数
       CacheItemRemovedCallback onRemove = null;//CacheItemRemovedCallback对象
       private  string CacheName = "UpdateHitsForExpired";//缓存名称
       private object LockForAddHits = new object();//LockForAddHits锁
       private object LockForItemRemovedFromCacheHits = new object();//ItemRemovedFromCacheHits        锁

       /**//// <summary>
       /// 构造函数
       /// </summary>
       public CounterHelper(string filename)
       {
           _FileName = filename;
           CacheName = filename;
           HttpContext ctx = HttpContext.Current;
           FilePth = ctx.Server.MapPath("~/" + _FileName + ".txt");
      ErrorLogFilePth = ctx.Server.MapPath("~/" + _FileName + ".txt");
          LoadHits();
      }

      /**//// <summary>
      /// 将累计点击数保存到全局变量,当它达到一定量时保存到文本文件,并清空
      /// </summary>
      public  void AddHits()
      {
          lock(LockForAddHits)
          {
              if( Hits != 0 )
              {
                  Add();
                  if(Hits > 200 )
                  {
                      //--移除                       
                      HttpRuntime.Cache.Remove(CacheName);
                  }
              }
              else
              {
                  onRemove = new CacheItemRemovedCallback(ItemRemovedFromCache);
                  HttpRuntime.Cache.Insert(
                      CacheName,
                      "This Object For Expired",
                      null,
                      DateTime.Now.AddSeconds(5) ,
                      TimeSpan.Zero,
                      System.Web.Caching.CacheItemPriority.Normal,
                      onRemove
                      );
                  Add();                   
              }
          }
      }           

      /**//// <summary>
      /// 保存到文本文件
      /// </summary>
      /// <param name="AllId"></param>
      private  void SaveHitsToFile(int hits)
      {
          string hitsinfo = string.Empty;           

          DateTime LastWriteTime = File.GetLastWriteTime(FilePth);
          if((DateTime.Today - LastWriteTime).TotalDays >0 )
          {
              //--表示今天第一次写数据
                HitsArr[1] = HitsArr[2];//--将当前累计的点击数赋给昨天的点击数
                HitsArr[2] = hits;//--设置今天的点击数
                using(StreamWriter streamWriter = new StreamWriter(FilePth,false) )
                {
                    streamWriter.Write(string.Format("{0},{1},{2}",HitsArr[0] + hits,HitsArr[1]   ,hits));
                    streamWriter.Flush();
                }
            }
            else
            {
                using(StreamWriter streamWriter = new StreamWriter(FilePth,false) )
                {
                    streamWriter.Write(string.Format("{0},{1},{2}",HitsArr[0] + hits,HitsArr[1],     HitsArr[2] + hits));
                    streamWriter.Flush();
                }
            }
        }   
       
        /**//// <summary>
        /// 当缓存被移除或过期是触发的回调事件
        /// </summary>
        /// <param name="key"></param>
        /// <param name="value"></param>
        /// <param name="reason"></param>
        private  void ItemRemovedFromCache(string key, object value,CacheItemRemovedReason       reason)
        {
            try
            {
                //清空并写到文本文件

                #region 
                int  hits = 0;;
                lock(LockForItemRemovedFromCacheHits)
                {
                    hits = Hits;
                    HitsArr[0] += hits;
                    HitsArr[2] += hits;
                    Hits = 0;
                }
                if(hits == 0)
                {
                    return;
                }
                else
                {
                    SaveHitsToFile(hits);
                }               
                #endregion
            }
            catch(Exception ex)
            {
                using(StreamWriter streamWriter = new StreamWriter(ErrorLogFilePth,false) )
                {
                    streamWriter.Write(string.Format("时间:{0}/r/n描述信息:{1}/r/n",DateTime.       Now,ex.Message));
                    streamWriter.Flush();
                }
            }
        }

        /**//// <summary>
        /// 获取所有的点击数
        /// </summary>
        public int AllHits
        {
            get
            {
                return HitsArr[0] + Hits;
            }
        }

        /**//// <summary>
        /// 获取昨天点击数
        /// </summary>
        public  int YesterdayHits
        {
            get
            {
                return HitsArr[1];
            }
        }   

        /**//// <summary>
        /// 获取今天点击数
        /// </summary>
        public  int TodayHits
        {
            get
            {
                return HitsArr[2] + Hits;
            }
        }

        /**//// <summary>
        /// 加载点击数
        /// </summary>
        private  void LoadHits()
        {
            if (HttpRuntime.Cache[CacheName] == null)
            {
                HttpContext ctx = HttpContext.Current;
                if (!File.Exists(FilePth))
                {
                    //--第一次使用
                    using (StreamWriter streamWriter = new StreamWriter(FilePth))
                    {
                        streamWriter.Write(string.Format("{0},{1},{2}", 0, 0, 0));
                        streamWriter.Flush();
                    }
                    HitsArr[0] = 0;
                    HitsArr[1] = 0;
                    HitsArr[2] = 0;
                }
                else
                {
                    string hitsinfo = string.Empty;
                    using (StreamReader objStreamReader = new StreamReader(FilePth))
                    {
                        hitsinfo = objStreamReader.ReadLine();
                    }
                    if (hitsinfo != "")
                 {
                     string[] arr = hitsinfo.Split(',');
                        HitsArr[0] = Convert.ToInt32(arr[0]);//全部
                        HitsArr[1] = Convert.ToInt32(arr[1]);//昨天
                        HitsArr[2] = Convert.ToInt32(arr[2]);//今天
                    }
                    else
                    {
                        HitsArr[0] = 0;
                        HitsArr[1] = 0;
                        HitsArr[2] = 0;
                    }
                }
                HttpRuntime.Cache["b" + CacheName] = HitsArr;
            }
            else
            {
                HitsArr = (int[])HttpRuntime.Cache["b" + CacheName];
                //HitsArr[0] += 1;
                //HitsArr[2] += 1;

            }
        }


        /**//// <summary>
        /// 获取累计的点击数
        /// </summary>
        private  int Hits
        {
            get
            {
                return    _Hits;
            }
            set
            {
                _Hits = value;
            }
        }

        /**//// <summary>
        /// 累加
        /// </summary>
        /// <param name="id"></param>
        private  void Add()
        {
            if(HitsArr[2]<14000)
            {
                //_Hits = _Hits + new Random(DateTime.Now.Second).Next(60,80);
                _Hits = _Hits + 1;
            }
            else
            {
                _Hits = _Hits + 1;//_Hits = _Hits + new Random(DateTime.Now.Second).Next(2,8);       传回指定范围的随机数
            }
        }
        /**//// <summary>
        /// 文件名
        /// </summary>
       
        /// <summary>
        /// 获取文件名
        /// </summary>
        public string FileName
        {
            get { return _FileName; }
            set { _FileName = value; }
        }
    }
}


2.创建HttpHandler

<%@ WebHandler Language="C#" class="HttpHandler" %>

using System;
using System.Web;
using System.Text.RegularExpressions;


namespace MYSpace.Counter
{
    /// <summary>
    /// HitsHandler 的摘要说明。
    /// </summary>
    public class CounterHandler : IHttpHandler
    {
        public void ProcessRequest(HttpContext ctx)
        {
            CounterHelper objCounterHelper = new CounterHelper(ctx.Request.QueryString["id"].ToString());
            objCounterHelper.AddHits();
            ctx.Response.Write(string.Format("document.write('页面访问量:{0} 昨日:{1} 今日:{2}  id :{3}')", objCounterHelper.AllHits, objCounterHelper.YesterdayHits, objCounterHelper.TodayHits, ctx.Request.Url.AbsoluteUri));
        }


        public bool IsReusable
        {
            get
            { return false; }
        }

    }
}


生成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>

这里只介绍到写入文件,如果想写入库里面,直接读取文件里的数值就搞定!