zoukankan      html  css  js  c++  java
  • 利用自定义IHttpModule来实现URL地址重写

        一般来说,要显示一些动态数据总是采用带参数的方式,比如制作一个UserInfo.aspx的动态页面用于显示系统的UserInfo这个用户信息表的数据,那么需要在其后带上一个参数来指定要显示的用户信息,比如UserInfo.aspx?UserId=1用于显示表中编号为1的用户的信息,如果为2则显示表中编号为2的用户信息。在一些系统中我们可能看到的不是这样的效果,可能会看到形如UserInfo2.aspx这样的形式(当然形式可以多样,只要有规律就行),当点击这样一个链接时看到的效果和UserInfo.aspx?UserId=2的效果一样,这里就用到了URL地址重写的目的。在其它动态语言如asp、JSP、PHP中要实现URL地址重写需要借助于其它的手段(有一些现成可用的用于实现URL地址重写的dll库),使用这些第三方手段时需要对IIS做些配置,如果网站放置在购买的虚拟主机上可能就不能够使用了(这种情况我以前就遇见过,当时曾经做过一个J2EE的网站放在虚拟主机上要对Tomcat做配置才能启用数据库连接池,但是虚拟主机提供商不提供这种服务),其实在ASP.NET中可以通过自定义IHttpModule就可以实现URL地址重写。

     

    以下文字摘自《ASP.NET夜话》一书第十二章:

     

         “从客户端向IIS发出请求到客户端得到请求的结果这个过程中有一些复杂的操作,涉及到一些非托管的类和非托管的方法,这里就不提了。在托管环境中第一个处理这个请求的类是ISAPIRuntime类。

    在ISAPIRuntime类中的ProcessRequest()方法中实例化HttpWorkerRequest类的实例,接着将HttpWorkerRequest的实例作为参数交由HttpRuntime类处理,然后在HttpRuntime类中实例化HttpContext类的实例(这个HttpContext的实例中包含了当前HTTP请求的所有特定HTTP信息,为实现了 IHttpModule 和 IHttpHandler 接口的类提供了对当前 HTTP 请求的 HttpContext 对象的引用,提供对请求的内部 Request、Response 和 Server 属性的访问),再将HttpContext的实例作为参数交由HttpApplicationFactory类(此类是interal的,在外部程序集是不可见的,MSDN中也找不到此类的说明)用于实例化HttpApplication类的实例,在实例化HttpApplication类的实例的同时还会根据web.config中的配置(包括系统级和当前网站或虚拟目录级)实例化所有实现IHttpModule接口的集合,这个集合是HttpModuleCollection类的实例,然后将HttpApplication类的实例作为参数依次调用HttpModuleCollection中的每一个实现了IHttpModule接口的类的实例的Init()方法。

    在这个Init()方法中开始处理一系列HttpApplication类的实例的事件。”

     

        上面的文字中讲到在实例化HttpApplication类时会根据web.config中的配置(包括系统级和当前网站或虚拟目录级)实例化所有实现IHttpModule接口的集合,然后会将HttpApplication类的实例作为参数依次调用每个实现了IHttpModule接口的类的实例的Init()方法,在Init方法中可以添加对请求的特殊处理。在HttpApplication中有很多事件,其中第一个事件就是BeginRequest事件,在这个事件中我们可以对用户请求的URL进行判断,如果满足某种要求,可以按另外一种方式来进行处理。

     

        比如,当接收到的用户请求的URL是UserInfo(//d+).aspx这种形式时(这里采用了正则表达式,表示的是UserInfo(数字).asp这种URL)我们将会运行UserInfo.aspx?UserId=(//d+)这样一个URL,这样网页就能正常显示了。

     

        当然实现URL地址重写还需要借助一个类:HttpContext。HttpContext类中定义了RewritePath 方法,这个方法有四种重载形式,分别是:

     

    RewritePath(String)  使用给定路径重写 URL。

    RewritePath(String, Boolean)  使用给定路径和一个布尔值重写 URL,该布尔值用于指定是否修改服务器资源的虚拟路径。

    RewritePath(String, String, String)  使用给定路径、路径信息和一个布尔值重写 URL,该布尔值用于指定是否修改服务器资源的虚拟路径。

    RewritePath(String, String, String, Boolean)  使用给定虚拟路径、路径信息、查询字符串信息和一个布尔值重写 URL,该布尔值用于指定是否将客户端文件路径设置为重写路径。

     

        对于这里四个重载方法的区别我不一一详细描述,因为在这里只用带一个参数的重载方法就能满足本文提出的要求。

     

    我们的步骤如下:

     

        首先编写自定义IHttpModule实现,这个定义只定义了两个方法Dispose()和Init()。在这里我们可以不用关注Dispose()这个方法,这个方法是用来实现如何最终完成资源的释放的。在Init方法中有一个HttpApplication参数,可以在方法中可以自定义对HttpApplication的事件处理方法。比如这里我们的代码如下:

     

    public void Init(HttpApplication context)  
    {  
        //context.BeginRequest是开始处理HTTP管线请求时发生的事件
        context.BeginRequest += new EventHandler(context_BeginRequest);  
        //context.Error是当处理过程中发生异常时产生的事件
        //context.Error += new EventHandler(context_Error);  
    }  

     

    然后在context_BeginRequest这个方法中自己编写处理事件,我们编写的代码如下:

    void context_BeginRequest(object sender, EventArgs e)  
    {  
        HttpApplication application = (HttpApplication)sender;  
        HttpContext context = application.Context;  
        HttpResponse response = context.Response;  
        string path = context.Request.Path;  
        string file = System.IO.Path.GetFileName(path);  
        //重写后的URL地址
        Regex regex=new Regex("UserInfo(//d+).aspx",RegexOptions.Compiled);  
        Match match=regex.Match(file);  
        //如果满足URL地址重写的条件
        if(match.Success)  
        {  
            string userId = match.Groups[1].Value;  
            string rewritePath = "UserInfo.aspx?UserId=" + userId;  
            //将其按照UserInfo.aspx?UserId=123这样的形式重写,确保能正常执行
            context.RewritePath(rewritePath);  
        }  
    }  

        注意在上面的代码中采用了正则表达式来进行匹配,使用正则表达式的好处就是在处理格式化文本时相当灵活。除此之外,我们在处理方法中仅仅对满足要求的URL进行重写,对于不满足要求的URL则无需进行重写,所以这样就不会干扰没有重写的URL的正常运行(比如Index.aspx)。

     

        从那段从《ASP.NET夜话》摘出的话中可以看出,仅仅是编写自己的IHttpModule实现还是不够的,我们还需要让处理Web请求的程序直到我们编写的IHttpModule实现的存在,这就需要在web.config中配置。在本实例中只需要在本ASP.NET项目中的web.config节点中增加一个<httpModules></httpModules>节点(如果已存在此节点则可以不用添加),然后在此节点中增加一个配置即可,对于本实例,这个节点最终内容如下:

    <httpModules>
        <add name="UrlReWriter" type="UrlReWriter"/>
    </httpModules>

      

    这样我们的URL地址重写就成功了。

     

    下面一个演示显示用户列表的链接的页面设计代码:

    <%@ Page Language="C#" AutoEventWireup="true"  CodeFile="Default.aspx.cs" Inherits="_Default" %>  
     
    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">  
    <html xmlns="http://www.w3.org/1999/xhtml">  
    <head id="Head1" runat="server">  
        <title>无标题页</title>  
    </head>  
    <body>  
    <form id="form1" runat="server">  
        <div>  
        <ol>  
        <li><a href="UserInfo1.aspx" mce_href="UserInfo1.aspx">编号为1的用户信息</a></li>  
        <li><a href="UserInfo2.aspx" mce_href="UserInfo2.aspx">编号为2的用户信息</a></li>  
        <li><a href="UserInfo3.aspx" mce_href="UserInfo3.aspx">编号为3的用户信息</a></li>  
        <li><a href="UserInfo4.aspx" mce_href="UserInfo4.aspx">编号为4的用户信息</a></li>  
        <li><a href="UserInfo.aspx?UserId=5" mce_href="UserInfo.aspx?UserId=5">编号为5的用户信息</a></li>  
        </ol>  
        </div>  
    </form>  
    </body>  
    </html>  

    在UserInfo.aspx页面的设计代码如下:

    <%@ Page Language="C#" AutoEventWireup="true" CodeFile="UserInfo.aspx.cs" Inherits="UserInfo" %>
     <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> 
    <html xmlns="http://www.w3.org/1999/xhtml">   <head id="Head1" runat="server">
           <title>无标题页</title>
       </head>
       <body>
           <form id="form1" runat="server">
           <div>
                      <asp:Literal ID="Literal1" runat="server"></asp:Literal>           <br />
           <img src="images/13.jpg" mce_src="images/13.jpg" width="283" height="485" title="MM" /> 
          </div>
           </form>
       </body>
       </html>  

    UserInfo.aspx页面的对应逻辑代码如下:

    using System;  
    using System.Collections;  
    using System.Configuration;  
    using System.Data;  
    using System.Web;  
    using System.Web.Security;  
    using System.Web.UI;  
    using System.Web.UI.HtmlControls;  
    using System.Web.UI.WebControls;  
    using System.Web.UI.WebControls.WebParts;  
     
    public partial class UserInfo : System.Web.UI.Page  
    {  
        protected void Page_Load(object sender, EventArgs e)  
        {  
            if (!Page.IsPostBack)  
            {  
                string queryString = Request.QueryString["UserId"];  
                int userId=0;  
     
                if (int.TryParse(queryString, out userId))  
                {  
                    Literal1.Text = "这是编号为" + userId.ToString() + "的用户的信息。";  
                }  
                else  
                {  
                    Literal1.Text = "错误的参数";  
                }  
            }  
        }  
    }  

    程序的演示效果:

     

    点击进行了URL重写的链接的效果(即UserInfo1.aspx):

     

    点击没有进行URL地址重写的页面的效果(即UserInfo.aspx?UserId=5):

     

    可见尽管我们进行了URL地址重写并不会页面的最终显示效果,因为最终实际执行的还是UserInfo.aspx?UserId=数字这种形式的URL。

     

    如果有兴趣还可以对全站进行伪静态化处理,所谓的伪静态化就是所有的链接在浏览器地址栏里看到的都是.html这样的形式,实际上执行的仍是动态页面,不过这就需要对IIS进行配置才行。为了简单期间,本文中没有使用数据库,即使使用数据库,只要重写前的页面能够正常显示,重写之后是不会有什么影响的。

     

    转自:http://hi.baidu.com/michaelwei/blog/item/44ed3e00fa5db11c1d958383.html

  • 相关阅读:
    java基础部分的一些有意思的东西。
    antdvue按需加载插件babelpluginimport报错
    阿超的烦恼 javaScript篇
    .NET E F(Entity Framework)框架 DataBase First 和 Code First 简单用法。
    JQuery获得input ID相同但是type不同的方法
    gridview的删除,修改,数据绑定处理
    jgGrid数据格式
    Cannot read configuration file due to insufficient permissions
    Invoke action which type of result is JsonResult on controller from view using Ajax or geJSon
    Entity model数据库连接
  • 原文地址:https://www.cnblogs.com/poissonnotes/p/2252825.html
Copyright © 2011-2022 走看看