当前位置:编程学习 > asp >>

技术原理解析[4:我记录框架 路由系统]

源代码位置:wojilu.Web.Mvc.Processors:RouteProcessor.cs

              :wojilu.Web.Mvc.Routes     :RouteTool.cs
客户端向服务器发送请求,主要是通过 url 链接的形式,是 url 告诉了服务器,应该返回什么样的信息。
路由(route)系统的目的,主要也就是将 url 解析成特定的数据,比如 url 中的 controller 是什么,action 是什么,id 又是什么,翻页是第几页等等。


如果还记得上一篇文章的话,wojilu系统通过IhttpHandler获得页面请求后,首先执行的就是RouteProcess,对的,第一步就是将请求的URL进行路由处理。

 Config ->

    wojilu.Web.Mvc.CoreHandler.ProcessRequest - >

          wojilu.Web.Mvc.CoreHandler.ProcessRequest: ProcessContext.Begin ->

               RouteProcess


 

 我们看看RouteProcess的主方法里面干了一些什么:
 

 1         public override void Process( ProcessContext context ) {
 2
 3             MvcEventPublisher.Instance.BeginParseRoute( context.ctx );
 4             if (context.ctx.utils.isSkipCurrentProcessor()) return;
 5
 6             Route r = RouteTool.Recognize( context.ctx );
 7             context.ctx.utils.setRoute( r );
 8
 9             IsSiteClosed( context.ctx );
10         }
首先,通过EventPublisher向系统进行广播,我们现在要开始一个路由解析过程了,这个时候如果有其他监听者的话,可以进行一些预处理工作。接下来看看这个过程是不是可以Skip掉,在wojilu里面,可以在结束当前Process的时候设定下一个Process是否可以Skip(跳过)。当然,这里理由是第一个Process,不会Skip掉的。


在 wojilu mvc 中有一个 RouteTool,就是专门用来解析 url 的。解析完成的路由信息将放入ProcessContext传递到下一个Process中。

ProcessContext是一个巨大的内容容器,里面放着每一个请求的所有信息。在每一个Process后,都可能改变或者追加内容。
最后,判断一下,当前这个网站是否处于关闭状态。wojilu可以通过后台来控制网站是否对外公开。如果网站现在处于关闭状态的话,这个时候还需要检查一下是不是在请求网站后台登陆页面,如果是网站后台登陆页面的话,则进行后续操作;如果处于关闭状态,又非网站后台登陆页面的话,则将预设的关闭理由输出到用户请求页面,请求处理结束。
 

 1         private void IsSiteClosed( MvcContext ctx ) {
 2
 3             Boolean isAdmin = isSiteAdmin( ctx.route );
 4
 5             if (!config.Instance.Site.IsClose || isAdmin != false) return;
 6             ctx.web.ResponseWrite( config.Instance.Site.CloseReason );
 7             ctx.web.ResponseEnd();
 8         }
 9
10         private Boolean isSiteAdmin( Route route ) {
11             String ns = route.ns;
12             if (strUtil.IsNullOrEmpty( ns )) return false;
13             if (ns.StartsWith( "Admin." ) || ns.Equals( "Admin" )) return true;
14             return false;
15         }
 

Route r = RouteTool.Recognize( context.ctx );

通过 Recognize 方法,就得到了结果,也就是一个 Route 对象,各属性的值是:
ctx.route.id 当前ID(整数)
ctx.route.controller 当前控制器(字符串)
ctx.route.action 当前控制器的方法(字符串)
ctx.route.owner 被访问对象(字符串)
ctx.route.ownerType 被访问对象的类型(site/group/user等)(字符串)
ctx.route.appId 当前应用程序的appId(有时候可以为0)(整数)
ctx.route.page 当前页面(在翻页的时候出现)(整数)
ctx.route.query 当前url中的查询字符串(QueryString)(字符串)

 

wojilu mvc 在解析并获取到这些值之后,会传递给 MvcContext,然后框架根据 controller 和 action 的字符串,创建相应的 controller 对象。这些过程,都是框架自动处理的。所以,开发者一般不需要用到 ctx.route.controller 等的字符串的值。

下面举个例子,比如 Article/2/Edit.aspx 这个 url ,在被解析之后,其实对应着 ArticleController 的 Edit(int id) 方法;
而 Article/2.aspx 这个 url,在被解析之后,则对应着  ArticleController 的 Show(int id) 方法,默认 Show 方法不在 url 中显示。

基本上,开发者不用操心链接的生成和路由的解析这个事情。只有在你需要自定义路由解析规则的时候,才需要理解下面的内容。

一、常规路由

路由的规则是由配置文件 /framework/config/route.config 定义的:

\
我 们看第三行,这条规则把 url 分成两部分,controller和id部分,如果一个 url 是由两部分组成,并且第二部分符合后面的要求(requirements)是整数,那么这个 url 的第一部分就是 controller,第二部分就是 id,比如 Article/3.aspx 的控制器就是 ArticleController(Controller后缀会自动补上),ID就是 3。

下面几行路由规则的解析原理依次类推。

那 么,第一条路由(第一行那个)是什么意思?它表示,如果请求的 url 是 default.aspx ,则默认(default)使用 MainController;但它没有指定默认的action。在没有 id 的情况下,默认的 action 是 Index;如果有 id ,则默认的 action 是 Show。

二、自定义路由

有些网址比较长,比如 www.wojilu.com 的论坛网址实际是: http://www.wojilu.com/Forum1/Forum/Index 在域名后面的路径为 /Forum1/Forum/Index ,不容易记忆,这时候,自定义路由就派上了用场。请在 route.config 中增加一行:
    bbs;default:{ownertype=site,owner=site}

你 可以和原先 route.config 中的第一行比较一下,其实是差不多的。它的意思是,bbs.aspx 将被解析到 site 对象的默认 controller 的默认 action 上,但是奇怪的是,没有定义默认的 controller?这是“我记录网站综合系统”在路由基础上,额外增加的一个功能,就是默认controller根据数据库中的菜单设置决定。这部分 你可以进一步参考“我记录网站综合系统”。

我们甚至可以将首页指向特定的用户,比如某用户名的友好url是 zhangsan,那么如果你第一行修改成这样:
    default;default:{owner=zhangsan,ownertype=user}

那么,用户访问网站首页,就会直接看到 zhangsna 这个用户的空间首页。顺便说一下,这意味着你完全可以把 “我记录网站综合系统” 这个多用户系统当做个人独立博客使用, 比起那些单用户博客系统来说,要方便、强大得很多。这就像你把 windows 2003 当 windows xp 用,把wondows 2008当 windows 7 用一个道理。另外,这样使用还有个好处,就是一旦你的独立博客有了一定知名度,你完全可以简单修改一下路由,就把它转换成支持“论坛/SNS”等在内的多 用户系统。
三、查询参数
我们先看一下传统的方式。在传统的web开发中,一个页面向另外一个页面传递参数,是通过queryString的方式进行的,也就是在网址后面附上一个问号和几个参数列表,比如:
/product.aspx?factory=联想&category=pc
然后在服务端通过 Request.QueryString( "factory" ) 和 Request.QueryString( "category" ) 依次获得 factory 和 category 的值。
在wojilu框架中,这种方式仍然支持。但对 Request.QueryString

补充:Web开发 , ASP.Net ,
CopyRight © 2012 站长网 编程知识问答 www.zzzyk.com All Rights Reserved
部份技术文章来自网络,