JSF请求处理过程(二)请求处理过程总览(FacesServlet#service)
更新日期:2009-07-20 点击:这总览,很明显是看FacesServlet的service方法。在FacesServlet的初始化过程中,构造出了全局的FacesContextFactory对象和LifeCycle对象。可以把FacesContextFactory看做是一个“请求包装工厂”,于是很明显,每当一个请求到达FacesServlet的时候,第一步便是拿着请求,到包装工厂里面包装一下,而包装的结果就是一个FacesContext。代码如下:
1 FacesContext context = facesContextFactory.getFacesContext(servletConfig.getServletContext(), request, response, lifecycle); 
在包装过程中,实际上是创建了一个com.sun.faces.context.FacesContextImpl对象,FacesContextImpl类继承了jsf-api项目中的javax.faces.context.FacesContext。FacesContextImpl的构造方法的第一个参数是一个叫做ExternalContext的接口的实现,查看其源代码,可以看到ExternalContextImpl类耦合了Servlet API,而FacesContextImpl与Servlet API无关。实际上,在这里,做到了JSF可以不仅仅使用在Servlet环境中,正如ExternalContext接口的注释中所说,在Servlet环境中使用JSF和在Portlet环境中使用JSF的不同,实际上就是使用了不同的ExternalContext。在FacesContextFactoryImpl中构造FacesContextImpl的代码如下:

Code highlighting produced by Actipro CodeHighlighter (freeware)
http://www.CodeHighlighter.com/

1 FacesContext ctx = new FacesContextImpl(new ExternalContextImpl((ServletContext) sc,(ServletRequest) request,(ServletResponse) response),lifecycle);
FacesContextImpl的构造方法中,还做了另外一件事情,就是根据配置确定了RenderKitFactory,显然不同的RenderKitFactory可以产生不同的RenderKit,而不同RenderKit对象是针对不同客户端的,所以对于浏览器、移动设备等等,会有不同的RenderKit。FacesContextImpl的构造方法中代码如下:

Code highlighting produced by Actipro CodeHighlighter (freeware)
http://www.CodeHighlighter.com/

1 this.externalContext = ec;
2 setCurrentInstance(this);
3 this.rkFactory = (RenderKitFactory)FactoryFinder.getFactory(FactoryFinder.RENDER_KIT_FACTORY);
在代码中我们经常使用FacesContext.getCurrentInstance()这个静态方法来获取与当前请求对应的FacesContext对象,实际上是在FacesContext类里面有一个静态的ThreadLocal对象用来存放了当前请求线程对应的FacesContext对象,于是上面的代码中setCurrentInstance(this)就是把当前构造出来的这个FacesContext对象放到了ThreadLocal里面。
FacesContext创建出来以后,正如上面所说,要让他经过LifeCycle这个“Filter Chain”的逐步处理了。那么,Filter Chain里面放的是一个一个Filter,那么LifeCycle这个Chain里面放的是什么呢?答案是Phases。
FacesServlet让FaceContext通过LifeCycle的处理,分成了两个部分。一个部分是调用LifeCycle的execute方法,执行逻辑,第二个部分是调用LifeCycle的render方法,呈现响应。FacesServlet.service中代码如下:

Code highlighting produced by Actipro CodeHighlighter (freeware)
http://www.CodeHighlighter.com/

1 lifecycle.execute(context);
2 lifecycle.render(context);
在LifeCycleImpl这个实现中,存放了一个Phase对象的数组,存放了7个Phase。其中第一个是null,然后依次是视图重建、应用请求值、验证、更新模型值、执行应用程序、呈现响应。在execute方法中,调用了从视图重建开始到执行应用程序为止的5个Phase,而在render方法中,调用了最后一个Phase,也就是呈现响应。在LifeCycleImpl类中,代码如下:

Code highlighting produced by Actipro CodeHighlighter (freeware)
http://www.CodeHighlighter.com/

//The Phase instance for the render() method
private Phase response = new RenderResponsePhase();

// The set of Phase instances that are executed by the execute() method
// in order by the ordinal property of each phase
private Phase[] phases = {
null, // ANY_PHASE placeholder, not a real Phase
new RestoreViewPhase(),
new ApplyRequestValuesPhase(),
new ProcessValidationsPhase(),
new UpdateModelValuesPhase(),
new InvokeApplicationPhase(),
response
};
在Servlet Filter中,可以由每一个Filter来决定是否要调用下一个Filter,从而决定是否让请求继续通过Filter Chains中的后续Filter,是链式调用的过程。而在LifeCycle的execute方法中,是用一个for循环顺序执行几个Phase。在每一个Phase执行完之后,都会检查FaceContext对象中是否设置了停止后续处理直接呈现响应的标志(renderResponse)或者已经完成了响应无需后续处理也不需要经过呈现响应阶段了(responseComplete),如果标志为true,那么就不再执行后续Phase。
LifeCycleImpl的execute方法主要代码如下:

Code highlighting produced by Actipro CodeHighlighter (freeware)
http://www.CodeHighlighter.com/

1 for (int i = 1, len = phases.length -1 ; i < len; i++) { // Skip ANY_PHASE placeholder
2
3 if (context.getRenderResponse() ||
4 context.getResponseComplete()) {
5 break;
6 }
7
8 phases[i].doPhase(context, this, listeners.listIterator());
9
10 }
在LifeCycle的render方法中,也会检查FacesContext的responseComplete状态,如果为true,那么就不再执行render Phase。于是我们此刻知道了在我们自己所写的一些代码或者JSF库里面的一些代码中,调用FacesContext的responseComplete方法和renderResponse得作用原理。render方法主要代码如下:

Code highlighting produced by Actipro CodeHighlighter (freeware)
http://www.CodeHighlighter.com/

1 if (!context.getResponseComplete()) {
2 response.doPhase(context, this,listeners.listIterator());
3 }
另外注意,Phase这个概念、接口,以及几个实现,都是jsf-ri项目中的,而在jsf-api中不存在Phase这个概念。所以,LifeCycle是JSF标准的内容,而通过几个Phase来处理请求这种实现是sun的参考实现的做法。
最后,可以看到对于每一个phase都调用了doPhase方法,同时把LifeCycle和FacesContext当做参数传入了。值得注意的是,所谓的phaseListener,也传入了phase的doPhase方法中,由此大约能够想明白这个“阶段监听器”的道理了。

JSF请求处理过程(二)请求处理过程总览(FacesServlet#service)相关推荐

  1. php是面向对象还是过程,PHP面向过程和面向对象

    php程序编写分为面向过程和面向对象.两者在功能实现上没有区别,但是在代码编写上区别很大,面向过程的代码很乱,不易管理,而面向对象把常用的功能封装为一个类,这样代码清楚多了. 下面举个小例子说明一下: ...

  2. ASP.NET Web API 过滤器创建、执行过程(二)

    ASP.NET Web API 过滤器创建.执行过程(二) 前言 前面一篇中讲解了过滤器执行之前的创建,通过实现IFilterProvider注册到当前的HttpConfiguration里的服务容器 ...

  3. 二阶矩过程、平稳过程和随机分析

    二阶矩过程和平稳过程 基本概念 主要讨论复随机过程与宽平稳过程. 二阶矩过程:对于 ∀ t ∈ T \forall t\in T ∀t∈T,均值和方差都存在. 严平稳过程:概率分布完全一样,不涉及数字 ...

  4. 【Android 异步操作】AsyncTask 异步任务 ( FutureTask 模拟 AsyncTask 执行过程 | AsyncTask 执行过程回顾 | FutureTask 分析 )

    文章目录 一.FutureTask 使用流程 二.FutureTask 模拟 AsyncTask 执行过程 三.AsyncTask 执行过程回顾 四.FutureTask 分析 一.FutureTas ...

  5. View工作原理(三)视图大小计算过程(measure过程)

    一.android中view的measure过程总概 视图大小计算的过程是从根视图measure()方法开始,接着该方法会调用根视图的onMeasure()方法,onMeasure()方法会对所包含的 ...

  6. Swift之深入解析构造过程和析构过程

    一.Swift 构造过程 构造过程是为了使用某个类.结构体或枚举类型的实例而进行的准备过程,这个过程包含了为实例中的每个属性设置初始值和为其执行必要的准备和初始化任务. Swift 构造函数使用 in ...

  7. 编写一个USB接口程序,模拟计算机启动过程和关闭过程启动过程中要加载鼠标、键盘、麦克风等USB设备,具体要求如下: (1)定义一个接口USB,包含两个抽象方法turnOn()he turnOff(),

    一.好物推荐 给大家推荐三款蓝牙耳机,下面的链接可以直接购买: 1.https://item.taobao.com/item.htm?ft=t&id=643733003968 2.https: ...

  8. mysql json储存过程_SQL-mysql储存过程

    一 前言 本篇内容是关于mysql储存过程的知识,学习本篇的基础是知识追寻者之前发过的文章(公众号读者看专辑) <SQL-你真的了解什么SQL么?> <SQL-小白最佳入门sql查询 ...

  9. 深入思考编译原理之 理解执行过程和编译过程

    在深入编译器原理细节之前,很多学习者并没有真正从宏观上理解一个编译器都做了些什么,这其实是非常遗憾的. 从计算机执行过程角度思考,函数调用的尤为重要,面向过程的语言更是将函数调用作为最基本的要素.面向 ...

最新文章

  1. 怎样预训练GNN能实现更好的迁移效果?
  2. KA,连接池居然这么简单?
  3. R 语言聚类关联规则
  4. [js] ajax请求地址只支持http/https吗?能做到让它支持rtmp://等其它自定义协议吗 ?
  5. 【转】Word 2010 取消拼写/语法检查,隐藏红线/绿线
  6. Dubbo自定义日志拦截器 1
  7. SQL Server 2012 无人值守安装(加入新实例)
  8. 写这么骚的代码,真不怕被同事揍么?
  9. 学生选课系统 c语言
  10. 100台电脑无盘服务器配置,100台网吧无盘系统配三星840PRO方案解读
  11. Arduino连接GPS模块
  12. 从零开始制作小车TB6612控制电机
  13. 画画不只是为了艺考,还能成为一门手艺~
  14. php screw.so,php screw加密
  15. 用python解“计算工资”题
  16. 关于VMD相关介绍(二)
  17. 内存模型系列(下)- 内存持久性模型(Memory Persistency)
  18. 如何设计好系统异常处理
  19. 0685-6.2.0-什么是Cloudera虚拟私有集群和SDX-续
  20. 图论-度序列可图性判断(Havel-Hakimi定理)

热门文章

  1. python 白色怎么表示_python – 如何使用pil使用白色背景(透明?)的round_corner标识?...
  2. API:互联网是如何在幕后工作的?
  3. C++11 并发指南六(atomic 类型详解三 std::atomic (续))
  4. 946. 验证栈序列
  5. order by + 数字的用意
  6. ActiveMQ、RabbitMQ、RocketMQ、Kafka的介绍及优缺点说明
  7. SQL Server含逗号分隔的数据匹配维表
  8. grid列的值格式化
  9. IM系统中如何保证消息的可靠投递(即QoS机制)(转)
  10. memcache两种客户端比较