王朝网络
分享
 
 
 

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

王朝other·作者佚名  2006-05-11
宽屏版  字体: |||超大  

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的实质。

 
 
 
免责声明:本文为网络用户发布,其观点仅代表作者个人观点,与本站无关,本站仅提供信息存储服务。文中陈述内容未经本站证实,其真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。
2023年上半年GDP全球前十五强
 百态   2023-10-24
美众议院议长启动对拜登的弹劾调查
 百态   2023-09-13
上海、济南、武汉等多地出现不明坠落物
 探索   2023-09-06
印度或要将国名改为“巴拉特”
 百态   2023-09-06
男子为女友送行,买票不登机被捕
 百态   2023-08-20
手机地震预警功能怎么开?
 干货   2023-08-06
女子4年卖2套房花700多万做美容:不但没变美脸,面部还出现变形
 百态   2023-08-04
住户一楼被水淹 还冲来8头猪
 百态   2023-07-31
女子体内爬出大量瓜子状活虫
 百态   2023-07-25
地球连续35年收到神秘规律性信号,网友:不要回答!
 探索   2023-07-21
全球镓价格本周大涨27%
 探索   2023-07-09
钱都流向了那些不缺钱的人,苦都留给了能吃苦的人
 探索   2023-07-02
倩女手游刀客魅者强控制(强混乱强眩晕强睡眠)和对应控制抗性的关系
 百态   2020-08-20
美国5月9日最新疫情:美国确诊人数突破131万
 百态   2020-05-09
荷兰政府宣布将集体辞职
 干货   2020-04-30
倩女幽魂手游师徒任务情义春秋猜成语答案逍遥观:鹏程万里
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案神机营:射石饮羽
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案昆仑山:拔刀相助
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案天工阁:鬼斧神工
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案丝路古道:单枪匹马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:与虎谋皮
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:李代桃僵
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:指鹿为马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:小鸟依人
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:千金买邻
 干货   2019-11-12
 
>>返回首页<<
推荐阅读
 
 
频道精选
 
静静地坐在废墟上,四周的荒凉一望无际,忽然觉得,凄凉也很美
© 2005- 王朝网络 版权所有