现在的位置: 首页 > 综合 > 正文

Discuz!NT 的URL地址重写(URLRewrite)

2013年10月03日 ⁄ 综合 ⁄ 共 4902字 ⁄ 字号 评论关闭

      声明:本文内容纯属个人观点,官方保留最终解释   

      在Discuz!NT中的前台页面访问(特别是aspx)是被HttpModule接管的,所以大家在Discuz.Web
项目的目录下看到的唯一"aspx文件"是index.aspx,而所有其它前台页面都有“/aspx/”文件夹下的相应
的子目录中,而这些子目录名称是与后台所“生成”的模板存在对应关系的。而这种“关系”的绑定是通
过dnt_templates(模板数据表)来进行关联的。而有关模板机制的文章详见:

    “Discuz!NT 模板机制分析”一文。

     今天所要说的其实是模板机制的“延续”,当然这种“延续”仅是我个人的观点。因为地址重写最终
要绑定的路径,恰恰与模板机制是有着前后呼应的关系。首先请大家看一下这张图:

        
     图1 :[discuz!NT 的web.config文件相关配置节]
    

      相信对于那些以前做过“URL重写”的朋友看到这一行配置的第一反映可能就是要去Discuz.Forum
.HttpModule类中一看究竟。同时考虑到在<httpModules>配置节中加入处理的资料在网上有许多,所
以这里就不再多费唇舌了。

      另外如果大家感兴趣味的话,也可以抽空看看我的这篇文章,"NET框架中的 Observer 模式"。虽
然该文是我在挖.net底层代码时是写的一些个人想法,可读性不高,但我相信会对大家有所帮助的:)

      好了,下面让我们看一下在Discuz.Forum项目中的HttpModule类中的一些信息,看看URL重写到
底如何实现:)
   

 1/// <summary>
 2 /// 论坛HttpModule类
 3 /// </summary>

 4 public class HttpModule : System.Web.IHttpModule
 5 {
 6         /// <summary>
 7  /// 实现接口的Init方法
 8  /// </summary>
 9  /// <param name="context"></param>

10  public void Init(HttpApplication context)
11  {
12    OnlineUsers.ResetOnlineList();
13   context.BeginRequest += new EventHandler(ReUrl_BeginRequest);
14  }

15
16 
17

18

 

      上面代码中的Init(HttpApplication context)是HttpModule类进行操作的入口,所有实现
System.Web.IHttpModule 接口的类都必须实现这个函数。
     同时大家看到的OnlineUsers.ResetOnlineList()方法主要是用于“重置(复位)在线表”,
而有关“在线用户”的功能我会在以后专门写文章来加以介绍,所以这里大家只要知道它要干的
事(代码如下)即可:)

        

 1  /// <summary>
 2  /// 复位在线表, 如果系统未重启, 仅是应用程序重新启动, 则不会重新创建
 3  /// </summary>
 4  /// <returns></returns>

 5  public static int ResetOnlineList()
 6  {
 7   try
 8   {
 9    // 取得在线表最后一条记录的tickcount字段 (因为本功能不要求特别精确)
10                //int tickcount = DatabaseProvider.GetInstance().GetLastTickCount();
11    // 如果距离现在系统运行时间小于10分钟
12    if (System.Environment.TickCount < 600000)
13    {
14     return InitOnlineList();
15    }

16    return -1;
17   }

18   catch
19   {
20    try
21    {
22     return InitOnlineList();
23    }

24    catch
25    {
26     return -1;
27    }

28   }

29
30  }

31
32

      而紧随其后的事件绑定代码就是一个关键点了,形如:
      

context.BeginRequest += new EventHandler(ReUrl_BeginRequest);

      因为当通过浏览器提交请求时,IIS都会接管请求进行相应的操作(详见DUDU的文章:" ASP.NET 2.0运行时
简要分析
")后,最终通过Web.config中的相应配置节(上图所示)来执行用户预定的处理操作。而我们的代码就
ReUrl_BeginRequest事件中(代码如下,详情见注释):

        

 1/// <summary>
 2        /// 重写Url
 3        /// </summary>
 4  /// <param name="sender">事件的源</param>
 5  /// <param name="e">包含事件数据的 EventArgs</param>

 6  private void ReUrl_BeginRequest(object sender, EventArgs e)
 7  {
 8                        //获取基本配置信息
 9   BaseConfigInfo baseconfig = BaseConfigProvider.Instance();
10            
11   if (baseconfig == null)
12          {
13                  return;
14              }

15
16                        //得到论坛配置信息
17              GeneralConfigInfo config = GeneralConfigs.GetConfig();
18   HttpContext context = ((HttpApplication)sender).Context;
19   string forumPath = baseconfig.Forumpath.ToLower();
20
21   string requestPath = context.Request.Path.ToLower();
22
23   if (requestPath.StartsWith(forumPath))
24   {
25    if (requestPath.Substring(forumPath.Length).IndexOf("/"== -1)
26    {
27     // 声明并设置默认论坛模板
28                   string strTemplateid = config.Templateid.ToString();
29     // 判断COOKIE中模板是否是系统当前的有效(已入库)模板
30                      if (Utils.InArray(Utils.GetCookie(Utils.GetTemplateCookieName()), 
31      Templates.GetValidTemplateIDList()))
32     {
33                           strTemplateid = Utils.GetCookie(Utils.GetTemplateCookieName());
34     }

35
36     //当访问的是首页时
37                      if (requestPath.EndsWith("/index.aspx"))
38                       {
39      //当配置文件中未指定首页时,则将forumindex.aspx做为首页并重写路径
40                           if (config.Indexpage == 0)
41                           {
42                                
43                                context.RewritePath(forumPath + "aspx/" + strTemplateid + "/forumindex.aspx");
44                           }

45                           else //否则使用聚合首页来做为网站首页并重写路径
46                           {
47                                
48                                context.RewritePath(forumPath + "aspx/" + strTemplateid + "/website.aspx");
49                           }

50
51                           return;
52                       }

53
54
55                       //当使用伪aspx, 如:showforum-1.aspx等.
56                       if (config.Aspxrewrite == 1)
57                       {
58      //获取后台设置的可以使用的伪aspx设置.
59      //SiteUrls.GetSiteUrls()类和方法说明见下文
60                           foreach (SiteUrls.URLRewrite url in SiteUrls.GetSiteUrls().Urls)
61                           {
62       //进行正则匹配,来看访问页面是否是用户定义的伪URL地址
63                                if (Regex.IsMatch(requestPath, url.Pattern, Utils.GetRegexCompiledOptions() | RegexOptions.IgnoreCase))
64                                {
65                                    string newUrl = Regex.Replace(requestPath.Substring(context.Request.Path.LastIndexOf("/")), url.Pattern, url.QueryString, Utils.GetRegexCompiledOptions() | RegexOptions.IgnoreCase);
66                                    
67                                    context.Re

抱歉!评论已关闭.