词条统计
浏览次数:7248 次
编辑次数:4次 历史版本
最近更新:2013/6/20
创建者:掷鸡蛋者

本文原是论坛帖子,讨论在此处:http://www.wojilu.com/Forum1/Topic/80?


总的流程分成两部分。

第一部分、包装 MvcContext

在 wojilu.Web.Mvc.CoreHandler 中,根据HttpContext,生成经过包装过的MvcContext(详细说明见此处:http://www.wojilu.com/Forum1/Topic/58?)。这个很简单。


第二部分,开始 mvc 的解析

整个 mvc 的解析流程(生命周期),是由 ProcessContext 控制的,请看它启动(Begin方法)的代码,依次装载了11个处理器(processor)



而这11个processor,就是 wojilu mvc 的整个解析流程。下面通过代码注释的办法,解释一下这11个processor的职责:

private static ListinitProcessor() {
??? Listlist = new List();
??? list.Add( new RouteProcessor() );????????????? //?根据url解析路由
??? list.Add( new InitContextProcessor() );????? //?初始化 "上下文" 相关数据(包括初始化当前controller)
??? list.Add( new ActionMethodChecker() );???? //?检查当前请求的方法(action)是否存在
??? list.Add( new ForbiddenActionChecker() ); //?检查当前action是否禁止访问
??? list.Add( new LoginActionChecker() );??????? //?检查当前action是否需要登录才能访问
??? list.Add( new HttpMethodChecker() );??????? //?检查当前http方法是否正确
??? list.Add( new PermissionChecker() );???????? //?重要:依次检查各级namespace是否做了权限控制
??? list.Add( new ActionProcessor() );???????????? //?关键:执行当前action,将controller的数据和view(视图模板)结合
??? list.Add( new LayoutProcessor() );??????????? //?根据当前action的结果,再加上当前controller的布局(layout)内容
??? list.Add( new NsLayoutProcessor() );??????? //?再加上各级namespace的布局内容
??? list.Add( new RenderProcessor() );?????????? //?将最终结果呈现给客户端
??? return list;
}


其中每一个 processor 执行之前,都引发 MvcEvent 事件,你可以自定义事件过滤器,在每一个processor执行之前,过滤每一个 processor。
换句话说,每一个 processor 都是可以扩展的。下图就是一个mvc过滤器的实现(详见:http://www.wojilu.com/Common/Page/48?):



下面依次解释比较重要的几个 processor。

第一,路由(route)解析。在 RouteProcessor 中完成。route解析完成之后,会将结果放入 MvcContext 中,其中的路由数据,主要是

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)(字符串)


第二,初始化上下文。 InitContextProcessor,它又分成6个部分。

initor.InitViewer( ctx ); //?初始化当前登录用户(访问者)?
initor.InitOwner( ctx ); //?初始化当前被访问对象(site或group或user)
initor.InitController( ctx ); //?初始化控制器
initor.InitPermission( ctx ); //?初始化权限检查(用处不大)

IList paths = PathHelper.GetPathList( ctx.route.getRootNamespace(), ctx.controller.GetType().Namespace );
ctx.utils.setLayoutPath( paths );
OnlineManager.Refresh( ctx ); //?刷新当前在线用户
initor.InitApp( ctx ); //?初始化当前app


对于“上下文初始化器(ContextInit)”,365最新体育网站_365体育网是假不假_365足球体育官方网站自带一个默认的。对于简单的系统来说就够了。但对于“我记录网站综合系统”这样比较复杂的应用来说,就需要自定义。

自定义的“上下文初始化器”必须继承自 ContextInitBase,你可以看“我记录网站综合系统”中的 wojilu.Web.Context.ContextInit 是如何实现的(在wojilu.core项目中) ,其中关键是初始化当前登录用户被访问对象,这两个对象是“我记录网站综合系统”的用户系统的核心概念,详解见此处:http://www.wojilu.com/Forum1/Topic/62

第三、检查各级权限

wojilu MVC framework在执行某控制器之前,会先从根命名空间开始,一级一级的检查,检查每个命名空间下是否有 SecurityController 这个控制器,如果有,就执行它的 CheckPermission 方法。而您可以在 CheckPermission 方法中,判断用户的权限。如果检查未通过,您可以使用 echo/ctx.applicationComplete 等方法终止程序的运行。
更多说明和示例见:http://www.wojilu.com/Common/Page/33??


第四、运行 controller 的 action 方法

这是整个mvc流程的核心。作用就是将数据和视图模板(view)结合。它也提供了扩展点,通过实现 IActionFilter 接口,你可以在action被执行之前或之后插入自定义的程序逻辑:


比如系统自带的数据库事务批注(attribute),就是一个action filter:


另外还有一个action缓存批注(attribute),也是同理实现的。

第五、加上各级布局

布局(layoute)相当于ASP.NET 中的 master page(母版页),但是可以根据namespace逐级增加,也可以手动隐藏。layout给系统提供了一个一致性呈现的效果。更多解释和示例见:?http://www.wojilu.com/Common/Page/12?