zoukankan      html  css  js  c++  java
  • DotText源码阅读(7) Pingback/TrackBack

    博客这种服务的区别于论坛和所谓文集网站,很大程度上我认为是由于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)吧。
  • 相关阅读:
    Django的路由系统
    Django框架简介
    域名与网站名的区别
    简单的链接样式-CSS
    用Javascript获取样式注意的地方
    null和undefined区别
    addLoadEvent(func)详解
    《Javascrip DOM 编程艺术》学习笔记-Chapter5
    某夜凌晨4点所感所悟——未来前端路
    win7-32bit-virtualbox安装问题及解决方式
  • 原文地址:https://www.cnblogs.com/jasononline/p/767207.html
Copyright © 2011-2022 走看看