我记录网站综合系统 -- 技术原理解析[11:ActionProcessor流程-wojilu核心]
这篇文章不是专门讲数据缓存的,但是这里有大量缓存内容,wojilu的缓存系统近期升级了,可能我的理解不是最正确的。
改日将会写专门的缓存文章。
源代码位置:\Web\Mvc\Processors:ActionProcessor.cs
wojilu.Web.Mvc.CoreHandler.ProcessRequest - >
wojilu.Web.Mvc.CoreHandler.ProcessRequest: ProcessContext.Begin ->
RouteProcessActionMethodChecker
ForbiddenActionChecker
LoginActionChecker
HttpMethodChecker
PermissionChecker
ActionProcessor
wojilu是一个MVC系统,以前的流程只是一些外围的东西,从这里开始,有点MVC的味道了。
下面对于ActionProcessor的主要处理分段介绍:
1。和其他Processor一样的处理,做广播,告知其他侦听者;如果可以跳过这步,则跳过,不过,由于是核心部分,这里跳过的可能性不多。获得上下文内容,进而获得其中的Controller。
2 if (context.ctx.utils.isSkipCurrentProcessor()) return;
3
4 MvcContext ctx = context.ctx;
5
6 ControllerBase controller = context.getController();
wojilu拥有一套缓存系统:下面这个步骤就是检查缓存。关于wojilu的缓存系统,曾经咨询过 作者 掷鸡蛋者。下面引用当时的邮件的内容:
2 /// 是否启用action缓存(如果关闭,所有action缓存都会失效)
3 /// </summary>
4 public Boolean IsActionCache { get { return _isActionCache; } }
5
6 /// <summary>
7 /// 是否启用页面缓存(如果关闭,所有页面缓存都会失效)
8 /// </summary>
9 public Boolean IsPageCache { get { return _isPageCache; } }
如果曾经这个Controller被访问过,第一次访问时候的数据将被缓存,直到数据被更新为止,缓存一直有效。下面的代码就是检查缓存。cacheKey 是Action的一个Key,在所有的Action缓存中,找寻缓存是否存在,如果存在的话,取得缓存内容,将内容放入当前的上下文中,接着从缓存里面获得页面的内容。由于直接从缓存中获得了需要的数据,整个过程在这里为止。
2 String cacheKey = null;
3 if (MvcConfig.Instance.IsActionCache) {
4
5 IActionCache actionCache = ControllerMeta.GetActionCache( controller.GetType(), ctx.route.action );
6
7 cacheKey = getCacheKey( actionCache, ctx );
8 if (strUtil.HasText( cacheKey )) {
9 Object cacheContent = checkCache( cacheKey );
10 if (cacheContent != null) {
11 logger.Info( "load from actionCache=" + cacheKey );
12 context.setContent( cacheContent.ToString() );
13 getPageMetaFromCache( ctx, cacheKey );
14 return;
15 }
16 }
17 }
getCacheKey
这里的ActionCache只是在GET的时候起作用。GET一般为了获取内容,POST一般是为了处理事件,所以这里的GET设计是非常好的。
2 if (actionCache == null) return null;
3 if (ctx.HttpMethod.Equals( "GET" ) == false) return null;
4 return actionCache.GetCacheKey( ctx, ctx.route.action );
5 }
getPageMetaFromCache
从缓存里面获取页面内容
2
3 PageMeta p = CacheManager.GetApplicationCache().Get( cacheKey + "_pageMeta" ) as PageMeta;
4 if (p != null) {
5 ctx.utils.setPageMeta( p );
6 }
7 }
这里的一个概念先说明一下:缓存里面的东西有2种,数据和页面布局.[应该是这样的]
我们在这里根据Action进行数据的获取或者处理,GET是获取,POST是处理。同时将获得的数据放入缓存(Action),以便下次使用,注意,这里是不分GET和POST的。这里的ActionRunner是实行业务逻辑的入口,在这里我们开始执行Action,也就是业务逻辑。同时将业务逻辑的结果放入缓存中。如果页面里面有INPUT的话,由于不能进行简单的替换,我们通过PostValueProcessor进行Input控件的值的设置和输入控件的验证错误的表示(在输入控件旁边标红,错误是前面业务逻辑执行的结果)。关于这部分,也和作者确认过了:以下是邮件原文:
这段的内容是做Action处理,加入缓存,最后将页面上的Input设置Value是吧。
例如 ActionRUn的时候做检索,结果加入缓存,然后设置结果页面上的Input?——是的,就是这个流程。其中ProcessPostValue是自动给表单赋值,如果有错误,同时给出错误提示。它的优点在于“自动”,我见过的所有框架,都需要手动在视图中提供错误的占位符,唯独wojilu是自动在form的顶部自动显示。见 http://www.wojilu.com/Common/Page/10 中的效果图:
2
3 // 设值模板并载入全局变量
4 setControllerView( controller, actionMethod );
5
6 // 运行并处理post值
7 ActionRunner.runAction( ctx, controller, actionMethod, controller.utils.runAction );
8 String actionContent = controller.utils.getActionResult();
9
10 // 加入缓存
11 if (MvcConfig.Instance.IsActionCache) {
12 if (strUtil.HasText( cacheKey )) {
13 addContentToCache( cacheKey, actionContent );
14 // 加入PageMeta
15 addPageMetaToCache( ctx, cacheKey );
16 }
17 }
18
19 actionContent = PostValueProcessor.ProcessPostValue( actionContent, ctx );
如果这个Action是一个Ajax局部页面的更新的话,我们将这个页面内容直接输出,ShowEnd可以指示后面的过程是否需要继续。showEnd 会跳过下面所有处理器,除了RenderProcessor[这个Processor不在前面所述的列表中,是一个单独的Processor,用来生成HTML字符串] 既然是一个AJAX,我们直接调用最后的RenderProcessor,生成HTML结果。如果是更新一个iFrame,也算是页面的一部分,我们获得需要的框架的HMTL后,同样ShowEnd。如果前面由于某些原因isEnd了,例如错误等等,这里也ShowEnd。不然的话,我们将Action的内容保存到上下文中,等待后续操作。最后如果是POST方法的话,数据可能有改动,所以我们updateActionCache,更新ActionCache。GET的时候不需要更新。
2
3 if (ctx.utils.isAjax) {
4 context.showEnd( actionContent );
5 }
6 else if (ctx.utils.isFrame()) {
7
8 int intNoLayout = ctx.utils.getNoLayout();
9
10 if (intNoLayout == 0) {
11
12 String content = MvcUtil.getFrameContent( actionContent );
13 context.showEnd( content );
14 }
15 else {
16 context.setContent( actionContent );
17 }
18
19
20 }
21 else if (ctx.utils.isEnd()) {
22 context.showEnd( actionContent );
23 }
24 else {
25 context.setContent( actionContent );
26 }
27
28 updateActionCache( ctx );
这篇文章是MVC的中核,关于数据缓存等内容,等1.7发布后再介绍