云联天下首页 |  登陆 |  注册 |  密码找回 |  关于我们 | 加入收藏 
首页技术资料网站建设→dotText源码阅读(5)--URLreWrite和Handler 【字号: 】 【背景色 杏仁黄 秋叶褐 胭脂红 芥末绿 天蓝 雪青 灰 银河白(默认色)

dotText源码阅读(5)--URLreWrite和Handler

网址来源:http://www.kehui.net发布时间: 2006-12-07 00:00:16
                Dottext需要映射全部不存在的文件到blog应用程序,实际上是需要IIS对于该应用下的问不进行处理,而是交给dottext程序处理,而dottext则利用一系列的handler来进行配置,对应不同的文件类型,或者匹配特定的文件,实现整个blog的URL 重写的。

        首先,是通过

<httpHandlers>

<addverb="*"path="*.asmx"type="System.Web.Services.Protocols.WebServiceHandlerFactory, System.Web.Services, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"validate="false"/>

              <addverb="*"path="Error.aspx"type="System.Web.UI.PageHandlerFactory"/>

<addverb="*"path="*"type="Dottext.Common.UrlManager.UrlReWriteHandlerFactory,Dottext.Common"/>

          </httpHandlers>

确保了任何对blog所在应用程序的访问都会被以上3个handler处理,如果是扩展名.asmx的http请求,会被系统缺省的处理程序处理;而对于错误处理(大多数都是转到error.aspx)会转入到系统的缺省aspx处理程序,其他任何请求都会转到Dottext.Common.UrlManager.UrlReWriteHandlerFactory,Dottext.Common  所以我们首先来看看这个处理句柄:

这是一个工厂类型的执行句柄,他自身并不进行处理。而是负责将请求根据不同的类别进行分别派遣,调出不同的处理程序进行执行,而这构成了dottext高效处理整个blog运行的精妙设计部分。

protected virtual HttpHandler[] GetHttpHandlers(HttpContext context)

         {

              return HandlerConfiguration.Instance().HttpHandlers;//这是个收集

         }

IhttpHandler接口的实现,用于返回处理http请求的全部句柄。而句柄配置在web.config中,所以dottext是这样获得全部handler的。而HandlerConfiguration.Instance()类似我们前面分析的配置处理体系那里的处理过程:

public static HandlerConfiguration Instance()

         {

              return ((HandlerConfiguration)ConfigurationSettings.GetConfig("HandlerConfiguration"));

         }

是从配置文件的xml片断中,获得产生具体的类实例,并经过反序列化后(请看看HandlerConfiguration的属性定义),得到一个句柄的数组,返回给UrlReWriteHandlerFactory的调用函数。具体为:

public virtual IHttpHandler GetHandler(HttpContext context, string requestType, string url, string path)

         {

              HttpHandler[] items = GetHttpHandlers(context);

              if(items != null)

              {

                   int count = items.Length;

                   string appStr=Dottext.Framework.Util.Globals.RemoveAppFromPath(context.Request.Path,context.Request.ApplicationPath);//得到访问哪一个应用程序的哪一个具体文件

                   for(int i = 0; i<count; i++)

                   {

                       //定向到特定的aspx文件

                        if(items[i].IsMatch(appStr))     //看看是否匹配系统配置中的者则表达式

                       {

                            //throw new Exception();

                            switch(items[i].HandlerType)

                            {

                                 case HandlerType.Page://默认是Page

                                     return ProccessHandlerTypePage(items[i],context,requestType,url);

                                 case HandlerType.Direct:                                   HandlerConfiguration.SetControls(context,items[i].BlogControls);

                                     return (IHttpHandler)items[i].Instance();

                                 case HandlerType.Factory:                                                                       return ((IHttpHandlerFactory)items[i].Instance()).GetHandler(context,requestType,url,path);

                                 default:

                                     throw new Exception("Invalid HandlerType: Unknown");

                            }

                       }

                   }

              }

              //如果请求的页面不匹配任何一个句柄,就使用ASP.NET的

              return PageHandlerFactory.GetHandler(context,requestType,url, path);

         }

获得全部web.config指定的handler以及正则表达式后,就进行匹配当前http访问请求的处理分析,如果请求的URL字符串匹配一个Page类型正则表达式(HttpHandler是一个实体类,通过反序列化后获得了type和Pattern属性,如果请求的资源是aspx或者html的,那么会进行正则式判断是否符合句柄的模式,)如果符合,那么同时就知道了句柄的类型,根据HandlerType.Page 、HandlerType.Direct、HandlerType.Factory进行分别处理。
如果是Page类型(某个aspx页面),那么执行:

private IHttpHandler ProccessHandlerTypePage(HttpHandler item, HttpContext context, string requestType, string url)

         {

              string pagepath = item.FullPageLocation;

              if(pagepath == null)

              {

                   pagepath = HandlerConfiguration.Instance().FullPageLocation;

              }

              HandlerConfiguration.SetControls(context,item.BlogControls);

              IHttpHandler myhandler=PageParser.GetCompiledPageInstance(url,pagepath,context);

              return myhandler;

         }

HandlerConfiguration.Instance()的代码如下:

public static HandlerConfiguration Instance()

         {

              return ((HandlerConfiguration)ConfigurationSettings.GetConfig("HandlerConfiguration"));

         }

同样,这也是配置文件通过反序列化得到一个HandlerConfiguration的实例,HandlerConfiguration的配置节内容在web.config中存在,我们会得到一个defaultPageLocation属性,FullPageLocation如果在属性无法获取的时候就返回defaultPageLocation的值,也就是说,通常我们访问某个目录,不带指定的aspx 的page文件名,就会自动访问defaultPageLocation.的指示的值。

SetControls 是针对部分页面的,就是类似<HttpHandlerpattern="/archive/d{4}/d{1,2}.aspx$"controls="ArchiveMonth.ascx"/>这类page 的,通常是指向一个用户控件,而大家知道用户控件实际上就是一个page。SetControls会把控件加入到当前请求的context重,以便执行期间从context中区的控件。

PageParser对象实际上是asp.net的解释对对象,它将指定的资源编译成程序集,这类似一个普通的物理存在的aspx页面执行机制。大家注意到,返回的是一个IhttpHandler对象,实际上asp.net的任何一个page都应该实现这个接口的,所以此处的逻辑就相当于执行了一个存在的页面。虽然页面可能不存在,但是通过配置指定最后得到了一个IhttpHandler对象处理了用户的http请求,这是Page类型的处理过程简要描述。

     第二类HandlerType是Direct ,有以下的http资源请求定向到这类Handler:

<HttpHandlerpattern="(.config|.asax|.ascx|.config|.cs|.vb|.vbproj|.asp|.licx|.resx|.resources)$"     type="Dottext.Framework.UrlManager.HttpForbiddenHandler, Dottext.Framework"handlerType="Direct"/>

              <HttpHandlerpattern="(.gif|.js|.jpg|.zip|.jpeg|.jpe|.css|.rar|.xml|.xsl)$"type="Dottext.Common.UrlManager.BlogStaticFileHandler, Dottext.Common"handlerType="Direct"/>    

 ......              <HttpHandlerpattern="/services/pingback.aspx$"type="Dottext.Framework.Tracking.PingBackService, Dottext.Framework"     handlerType="Direct"/>              <HttpHandlerpattern="/services/metablogapi.aspx$"type="Dottext.Framework.XmlRpc.MetaWeblog, Dottext.Framework"     handlerType="Direct"/>

              可以看到,大部分我们找不到实际的文件名,但是却可以通过访问blog下的url返回内容,系统根据url判断如何返回内容。我们举一个例子来看看Direct怎么执行的。看看<HttpHandlerpattern="/rss.aspx$"type="Dottext.Common.Syndication.RssHandler, Dottext.Common"     handlerType="Direct"/>

执行:

case HandlerType.Direct:                                   HandlerConfiguration.SetControls(context,items[i].BlogControls);

                                     return (IHttpHandler)items[i].Instance();

时候,会实例化一个Dottext.Common.Syndication.RssHandler类的实例(RssHandler是间接实现了IhttpHandler接口的),它继承自抽象类BaseSyndicationHandler,BaseSyndicationHandler实现了总体的返回特定格式RSS文档的功能和能力,通过继承覆盖,不同的格式的实现类(RSS20和ATOM等)实现了各自格式的rss文档返回给用户。总之,在这类的handler中,最终通过Context.Response操纵到客户的输出流。

     第三类的是Factory类型的,其自身就是一个工厂模式的handler,会再次将当前url转交给下一级handler,这样实现了可扩展性。如果dottext的新功能需要进一步处理URL得到其他功能就可以利用此类进行处理。譬如:

<HttpHandlerpattern="/(?:admin)"type="Dottext.Web.UI.Handlers.BlogExistingPageHandler, Dottext.Web"handlerType="Factory"/>

当用户访问应用程序下的/admin目录时候,自然处于该Dottext.Web.UI.Handlers.BlogExistingPageHandle 处理。由于是工厂模式,所以我们着重看看:

public virtual IHttpHandler GetHandler(HttpContext context, string requestType, string url, string path)

         {     BlogConfig config = Config.CurrentBlog(context);

              if(ConfigProvider.Instance().IsAggregateSite)

              {

                   string app = config.Application.ToLower();

                   url = Regex.Replace(url,app,"/",RegexOptions.IgnoreCase);

app = "\"+config.CleanApplication+"\";

                   path = Regex.Replace(path,app,"/",RegexOptions.IgnoreCase);

                   if(!Regex.IsMatch(path,".w+$"))

                   {

                       path = System.IO.Path.Combine(path,"index.aspx");

                   }

              }

              return PageParser.GetCompiledPageInstance(url, path, context);

         }

处理时候,首先取得当前blog的配置,ConfigProvider.Instance()返回一个Iconfig接口的实例,看看这个Instance的代码:

     static ConfigProvider()         //静态构造函数

         {

              ConfigProviderConfiguration cpc = Config.Settings.BlogProviders.ConfigProvider;

              config = (IConfig)cpc.Instance();

              config.Application = cpc.Application;

              config.CacheTime = cpc.CacheTime;

              config.Host = cpc.Host;

              config.ImageDirectory = cpc.ImageDirectory;

              config.BlogID = cpc.BlogID;             

         }

          private static IConfig config = null;

         public static IConfig Instance()

         {

              return config;

         }

执行静态构造函数,通过Config.Settings.BlogProviders.ConfigProvider反序列化得到ConfigProviderConfiguration。ConfigProviderConfiguration继承抽象类BaseProvider,通过BaseProvider的instance方法:

public object Instance()

         {

              return Activator.CreateInstance(System.Type.GetType(this.ProviderType));

         }

此处的ProviderType是通过反序列化得到:

[XmlAttribute("type")]

         public string ProviderType

         {

              get {     return _type;   }

              set { _type = value; }

         }

也就是

<ConfigProvidertype="Dottext.Common.Config.MultipleBlogConfig, Dottext.Common"host="localhost"     cacheTime="120"/> 中指明的MultipleBlogConfig 类型。MultipleBlogConfig继承自BaseBlogConfig , BaseBlogConfig实现了IConfig,所以你才看到

config = (IConfig)cpc.Instance();

然后,得到了相应的属性IsAggregateSite。该属性的意思是当前访问的是否是聚合站点(而不是但个博客的站点,只有聚合站点才可以使用存在的aspx文件)。确认聚合站点后,就取得应用程序目录下的实际aspx文件,然后利用CLR的功能PageParser.GetCompiledPageInstance(url, path, context)返回页面执行结果。

所有blog的http请求,依据URL通过正则表达式匹配到不同的Handler类型,实现了3种类别的处理,但最终用户看到的是请求执行结果。修改web.config我们可以进行特定资源的特殊执行,这是UrlReWrite的实质。

 





shanhe 

相关新闻
v 同时支持三种事件模型的javascript 2006-12-07 00:00:16
v 下一代软件架构--SOA 2006-12-07 00:00:16
v 什么是Web Service? 2006-12-07 00:00:16
v 比网易社区被黑更黑的内幕 2006-12-07 00:00:16
v 你未必知道的CSS技巧 2006-12-07 00:00:16
v Python我入门了,使用Python生成文本还是挺方便的 2006-12-07 00:00:16
v Asp.Net细节性问题技巧精萃 2006-12-07 00:00:16
v Flash+ColdFusion全新概念建站 2006-12-07 00:00:16
v 管理 XML 数据: 标签 URI 2006-12-07 00:00:16
v 一个创业者失去客户的六种错误 2006-12-07 00:00:16
  最新新闻
智慧家居
智慧家居颠覆传统智能家居
智慧云谷让智能家居变成有智慧的
智慧云谷引领智慧家居新生活
科技改变生活 智慧云谷智慧家居系
智慧家居领航者,智慧云谷助你玩
智能家居如何赢得市场美誉度?
智慧云谷智慧家居:创业者有无限
WiFi智能家居你还在用?这样的智
互联网+助推智能家居产业
智慧云谷为您打造真正的智能家居
智能家居产业需要的不是单品,而
新家如何选择开关?智慧云谷iWis
智能传感器-世界首款“智”为你的
智慧云谷开关智能安防智能空气质
智能开关品牌,如何选择智能开关
秋季干燥,智慧家居温湿度传感器
传感器助力智慧家居 感知爱家
iWiscloud智能触摸开关缔造家居装

  最新帖子
 ※这么冷清  [gabc111]
 ※植树节,智慧云谷为您  [于文强]
 ※智慧云谷智慧家居,国  [于文强]
 ※好消息,智慧云谷新风  [于文强]
 ※新家如何选择开关?智  [于文强]
 ※智慧云谷|2016广州国际  [于文强]
 ※手机APP操作有问题  [ssy11407]
 ※智慧云谷智慧家居将在  [cici]
 ※上传下载  [cici]
 ※下载智慧家居  [apple2008]
 ※秋季干燥,智慧家居温  [apple2008]
 ※智慧家居紧扣热点 安全  [apple2008]
 ※办公大楼如何智慧化管  [apple2008]
 ※智慧云谷工业自控的优  [apple2008]
 ※传感器助力智慧家居 感  [apple2008]
 ※智能开关品牌,如何选  [apple2008]
 ※智慧云谷开关智能安防  [apple2008]
 ※没有专业人员,如何安  [apple2008]
 ※烟台智慧云谷董事长任  [apple2008]
 ※互联网+助推智能家居产  [apple2008]
钯碳回收 硝酸银回收 银浆回收 银焊条回收 回收银浆 氯化钯回收 氯化钯回收 氧化钯回收 回收硝酸钯 钯水回收价格 海绵钯回收 钯炭回收价格 回收镀金板 深圳钯碳回收 镇江氯化钯回收 杭州钯浆回收 银浆回收多少钱 回收钯碳公司 硝酸银的价格 那里有回收金 氯化钯回收价格 江苏擦银布回收 硝酸银价格 德州钯粉回收 银铜回收 回收钯粉 回收铂碳催化剂 佛山钯碳回收 金盐回收价格 海绵钯回收 钯碳高价回收 钯回收价格 钯炭回收