DotText源码阅读(7) --Pingback/TrackBack

原创 2006年05月17日 01:22:00
博客这种服务的区别于论坛和所谓文集网站,很大程度上我认为是由于pingback/trackback的存在,使得博客这种自媒体有可以延展加入SNS的要素。所以分析博客程序,我们需要了解这种协议以及协议的实施细节。
       在dottext的源代码中,在发表作品中,我们可以看到有pingback协议的支持,同时在web services的实现中,有trackback协议的实现。至于什么是piongback/trackback协议,google下应当可以找到,也不用我费口舌。
              通过              <HttpHandlerpattern="/(?:admin)"type="Dottext.Web.UI.Handlers.BlogExistingPageHandler, Dottext.Web"handlerType="Factory"/>
的映射,使得我们访问每一个blog的admin目录时候,都会UrlRewrite到dottexweb/admin目录下的相对应aspx文件(参考前面部分),其中在发表post的时候,我们看到是这样一个调用关系:
       private void UpdatePost()
         {   
              if(Page.IsValid)
              {
                   string successMessage = Constants.RES_SUCCESSNEW;
                   try
                   {
                       Entry entry = new Entry(EntryType);
 
                        entry.Title = txbTitle.Text;
                        entry.Body = Globals.StripRTB(ftbBody.Text,Request.Url.Host);
                      
                        entry.BlogID = Config.CurrentBlog(Context).BlogID;
                      
                       if (PostID > 0)
                       {//是更新操作
                            successMessage = Constants.RES_SUCCESSEDIT;
                            entry.DateUpdated = DateTime.Now;//BlogTime.CurrentBloggerTime;
                            entry.EntryID = PostID;
                           
                            Entries.Update(entry);
                           
                       }
                       else
                       {//新建操作
                            entry.DateCreated = DateTime.Now;//BlogTime.CurrentBloggerTime;
                            PostID = Entries.Create(entry);       
                       }
                   }
                   catch(Exception ex)
                   {           }
                   finally
                   {            }
              }
     }
     Entries.Create(entry);是这样的:
         public static int Create(Entry entry, int[] CategoryIDs)
         {
              HandlerManager.PreCommit(entry,ProcessAction.Insert);            
              int result = DTOProvider.Instance().Create(entry,CategoryIDs);             
              if(result > 0)
              {
                   HandlerManager.PostCommit(entry,ProcessAction.Insert);                
              }
              return result;
     }
     最终的数据存储试调用DTOProvider也就是DataDTOProvider 最终是落到 SqlDataProvider 来实现数据存储操作。但是我们注意到 HandlerManager.PostCommit(entry,ProcessAction.Insert);     这个操作。仔细看看:
     HandlerManager 是一个关于Entry操作类的包装类(wapper class),PreCommit是这样定义的:
          Process(ProcessState.PreCommit,e,pa);
     而Process是这样读取web.config的
     public static void Process(ProcessState ps, Entry e, ProcessAction pa)
         {     //Do we have factories? 在疑惑是否该用工厂模式呢
              EntryHandler[] hanlers = Config.Settings.EntryHandlers;     //这是反序列化哦,这里的Config是Dottext.Framework.Configuration.Config
              if(e != null && hanlers != null)
              {     //walk the entries 遍历全部处理例程
                   for(int i = 0; i<hanlers.Length; i++)
                   {
                        EntryHandler handler = hanlers[i];
                        if(ShouldProcess(ps,handler,e.PostType,pa))
                       {
                            IEntryFactoryHandler ihandler = handler.IEntryFactoryHandlerInstance;                           
                            //Call the IEntryFactoryHandler configure method. This gives async items a chance to "ready" themselves
                            //before leaving the main thread and entering the managed queue.
                            ihandler.Configure();
                            if(handler.IsAsync)
                            {//Add factory to managed queue.
                                 EntryHanlderQueue.Enqueue(ihandler,e);
                            }
                            else
                            {
                                 ihandler.Process(e);
                            }
                       }
                      
                   }
              }
         }
ShouldProcess 是判断是预提交还是已经提交post,决定是否应该进行handler的实例化,如果是已经提交的Post,我们需要进行handler.IEntryFactoryHandlerInstance;      IentryFactoryHandlerInstance最终是通过
ihandler = (IEntryFactoryHandler)Activator.CreateInstance(Type.GetType(this.ItemType));
来实例化数组元素的().
经过实例化后,就可以执行了。此时根据 handler.IsAsync 的属性,决定是允许 EntryHanlderQueue.Enqueue(ihandler,e); 加入队列,还是马上处理
ihandler.Process(e);.
对于可以异步执行的静态函数 Enque 处理:
public static void Enqueue(IEntryFactoryHandler factory, Entry e)
         {
              EntryHanlderQueue ehq = new EntryHanlderQueue(factory,e);
              ManagedThreadPool.QueueUserWorkItem(new WaitCallback(ehq.Enqueue));
     }
构造一个实例,然后加入线程队列进行任务排队。线程管理暂不讨论。我们看看这几个EntryHandler.
TrackBack Handler是如何处理的呢?
public void Process(Dottext.Framework.Components.Entry e)
         {
              //Get a list of links from the current post
              StringCollection links = TrackHelpers.GetLinks(e.Body);
              if(links != null && links.Count > 0)
              {
                   //Instantiate our proxy
                   TrackBackNotificationProxy proxy = new TrackBackNotificationProxy();
                  
                   //Walk the links
                   for(int i = 0; i<links.Count; i++)
                   {
                       string link = links[i];
                       //get the page text
                       string pageText = BlogRequest.GetPageText(link,e.Link);
                        if(pageText != null)
                       {
                            try
                            {
                                 string desc = null;
                                 if(e.HasDescription)
                                 {
                                     desc = e.Description;
                                 }
                                 else
                                 {
                                      desc=string.Format("TrackBack From:{0}",e.Link);
                                      
                                 }   
desc = regexStripHTML.Replace(e.Body,string.Empty);
                                      if(desc.Length > 100)
                                     {
                                          int place = 100;
                                          int len = desc.Length-1;
                                          while(!Char.IsWhiteSpace(desc[place]) && i < len)
                                          {
                                               place++;
                                          }
                                          desc = string.Format("{0}...",desc.Substring(0,place));
                                     }
                                 }
                                 //attempt a trackback.
                            proxy.TrackBackPing(pageText,link,e.Title,e.Link,e.Author,desc);                           
                            }
                            catch(Exception ex)
                            {                                 Logger.LogManager.CreateExceptionLog(ex,string.Format("Trackback Failure: {0}",link));
                            }
                       }
                   }
              }
     }
 TrackHelpers.GetLinks 会分析Entry.Body字符串,获得post的全部href连结,也就是对外引用部分,这个TrackBack利用proxy.TrackBackPing(pageText,link,e.Title,e.Link,e.Author,desc); 将本文的对外引用通告刚刚获得的连接地址。
      
TrackBackPing :
    string pageText = BlogRequest.GetPageText(link,e.Link);会利用BlogRequest的http协议能力下载被引用地址的source code,然后 link为另外blog的地址,而e.Link为reffer,这是为了告知对方那个页面引用了link。经过安全解码后,获得了link的源代码,然后TrackBackPing会进行分析,找寻string sPattern = @"<rdf:/w+/s[^>]*?>(</rdf:rdf>)?";匹配的部分,分析出其中的引用通告地址。下一步就是利用SendPing(string trackBackItem, string parameters),向目标地址处post一个application/x-www-form-urlencoded"的数据。此即完成了一次trackBack.
  其他几个EntryHandler也是分同步和异步的,大家可以照此阅读。
    
    题外话:那些没有礼貌的实现pingback/Trackback的所谓blog,就不要妄自称自己为博客服务商(BSP)吧。

相关文章推荐

wordpress中的Pingback和Trackback到底有何区别

Trackback我们都知道是自己在自己的Blog上撰文回应别人的文章,那么别人的文章的回复中会有trackback from的字样.但是我很早又注意到有trackback和pingback之分,在很...

flashsim源码阅读7-8(2)

再次回到disksim_simulate_event()函数主体:void disksim_simulate_event (int num) { event *curr; if ((curr =...

Memcache源码阅读(7)---用户输入的处理

我看的源码版本是1.2.4前面我已经说了数据存储,哈希表的管理,内存的管理。还有第二章说到用户的请求时如何到达memcached的,从用户的输入到memcached如何接受到这些输入。那现在我们来分析...
  • Honkee_
  • Honkee_
  • 2016年12月25日 20:22
  • 151

flashsim源码阅读7-8(3)

参考论文阅读 参考论文:Flashsim:A Simulator for NAND Flash-based Solid-State Drives。 为了更好的理解该仿真器,去阅读了该仿真器设计者写...

redis源码阅读(7)-数据持久化RDB,AOF

Redis 持久化:提供了多种不同级别的持久化方式:一种是RDB,另一种是AOF.RDB 持久化可以在指定的时间间隔内生成数据集的时间点快照(point-in-time snapshot)。AOF 持...

MP4学习(九)ts-mp4源码阅读(7)mdia box的解析

mdia box的解析 常见的MP4结构图 mdia box的定义 /* ** mdia box的定义,...

caffe源码阅读7-neuron_layers.hpp+各cpp

neuron_layers.hpp: NeuronLayer类 AbsValLayer类 BNLLLayer类 DropoutLayer类 PowerLayer类 ReLULayer类,CuDNNR...

Hadoop 2.0源码阅读环境配置--win7+Eclipse+Hadoop2.2.0

hadoop 2.0发布时间不长,目前也还没有puji

【JDK源码阅读7-util】Map接口

Map接口      Map接口不是Collection的子接口;          *Map集合中将键映射到值的对象。一个映射不包含重复的键,即每个键最多映射一个值; *Map接口提供了三种c...

flashsim源码阅读(intq队列操作)7-8

推荐源码阅读的的工具是sourceInsight3.5,直接将源码文件导入,就会生成一个各文件关联的工程,这个工具可自行百度,配合Nodepad++修改注释阅读更好,因为SI不知道为什么对中文注释输入...
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:DotText源码阅读(7) --Pingback/TrackBack
举报原因:
原因补充:

(最多只允许输入30个字)