1.请求处理生命周期做了什么:处理进入的请求参数,还管理服务器端的用户界面组件集,并把它们与用户在客户端浏览器中看到的组件同步(即把服务器端的JavaBean属性自动同步到有层次的组件集的能力)。
2 JSF请求处理生命周期为何物:
处理进入的请求数据,通常需要不同类型的工作,包括检查进入的数据是否有效,触发服务器端的应用程序逻辑完成请求,以及最后把响应渲染给客户端。JSF请求处理生命周期用前后连贯的顺序执行这些任务,而且在一组定义良好的阶段的控制下。这种方式允许每个阶段清楚的描述执行本阶段之前需要存在的前提条件,以及本阶段执行之后会存在的后置条件。
3. JSF请求处理生命周期各个阶段:
(1)恢复视图:
因为JSF组件是服务器端组件,可以认为客户端显示的用户界面其实是JSF组件提供的一个镜像。所以此阶段的任务是根据前一个事物恢复现有视图,或者根据新请求创建新视图。如果是新请求,就创建新视图,并保存在父容器对象FacesContext内。
(2)应用请求值:
此阶段主要是对进入的请求值或名称-值对进行处理。即在用户界面组件视图(或UIViewRoot)上调用高级方法processDecodes(),把请求值应用到用户界面组件(所有子组件都会递归调用它们的processDecodes(),进行请求名称-值对的“解码”,把匹配的新值应用到用户界面组件的value属性)。注意一点的是,只有能容纳值的用户界面组件(如:InputText)才有新值应用到它们。
这里有个概念可能对以后会有帮助:所有具有value属性的组件都实现valueHolder接口。所有表单元素类型组件,如果它的值可以由用户编辑,那么就都实现了EditableValueHolder接口。所有引起动作的组件(按钮或连接)都实现ActionSource接口(对于JSF1.2动作组件实现的是ActionSource2接口,它允许使用1.2中新的统一EL)。
对于按钮在表单提交期间,不用更新新值,它只需记住自己是否被单击,如果单击就引起动作事件并进入事件队列中。
还要注意的是: JSF请求处理生命周期使用连贯的方式处理不同阶段,但阶段的执行顺序可以为特殊情况而变化。比如把组件的immediate属性设置为true,就会跳过所有验证,不处理表单的值,直接导航到另一页。当然不同的组件上设置immediate属性会有不同的效果。(大家可以自己动手做些实例)
(3) 处理验证:
处理完应用请求值后,就要执行对进入数据的转换和验证了。在这个阶段主要是调用processValidators()。即每个子组件都递归的执行此方法(和processDecodes()类似)
注意的是:数据类型的转换实际发生在验证之前,因为要验证必须先把数据转换成服务器端数据类型。
如果这个阶段出现错误,将会把FacesMessages消息放进FacesContext队列。当响应被渲染回用户,可以见到Message或Messages组件显示的消息。
(4) 更新模型值:
到这个阶段后,将把通过转换和验证的数据分配给值绑定到用户界面组件的模型对象。
这里的意思是:如果你有一个代表用户的JAVA类User,把它注册为托管bean,并用JSF表达式语言把属性绑定到页面上的不同用户界面组件,那么在这个阶段,实际的托管bean或模型对象的属性,被他们绑定的用户界面组件的新值更新。假如你在inputText组件中输入username(并且通过上面3个阶段)那么现在你在inputText中的值为username,此时你的User类的name属性也为username.(大家做实例去 体会吧)。
此阶段其实和其他阶段类似:在UIViewRoot上调用processUpdates()方法,对每个子组件都递归执行此方法。在这里如果存在类型为UIInput或者它的扩展组件就会调用updateModel()方法。其实这里揭示了一个秘密:只要把JavaBean属性绑定到一组JSF用户界面组件,就不需要手动编码,他们能自动更新。
(5) 调用应用程序:
这个部分是真正对取得的数据进行操作的阶段。
用户界面组件可以容纳值(实现EditableValueHolder)也可以是AcionEvent来源(实现ActionSource),即动作方法或动作侦听器就是在此阶段调用的。
在此阶段,UIViewRoot的processApplication()方法被调用,它又把队列中这个阶段的事件广播到每个实现ActionSrouce(JSF1.2ActionSrouce2)的UIComponent组件。这通过调用每个UIComponent的broadcast()方法做到的,实际上就触发了动作事件,接着由动作侦听器处理这些动作事件。可用默认动作侦听器编写定制动作方法或动作侦听器方法并绑定到UIComponent(实现了ActionSource的UIComponent)处理动作事件。
(6) 渲染响应:
在这个阶段,为了把整个响应渲染回客户端,将逐一对每个组件递归调用encodeXX()方法。
处理把响应渲染给客户端,渲染响应阶段还保存视图的当前状态,以便可以在后续web请求中访问恢复状态
其实在JSF1.2,渲染响应阶段被重新设计了,大家可以通过实例来感受下<f:verbatim>在1.1和1.2中添加和不添加f:verbatim<f:verbatim></f:verbatim>有什么变化。
现在渲染就先说到这里
这些只是幕后的工作,对于一般的人知道有这个概念就可以了,而对于想理解JSF高级特性的人来说(比如编写AJAX的JSF组件), JSF请求处理生命周期显得很重要,不过在刚看后不要着急自己是否弄懂了,在实践中体会比纸上谈兵更容易理解。希望大家在日后使用JSF的过程中一边做一边去联系下 JSF请求处理生命周期。会有很大收获的。</f:verbatim>
2 JSF请求处理生命周期为何物:
处理进入的请求数据,通常需要不同类型的工作,包括检查进入的数据是否有效,触发服务器端的应用程序逻辑完成请求,以及最后把响应渲染给客户端。JSF请求处理生命周期用前后连贯的顺序执行这些任务,而且在一组定义良好的阶段的控制下。这种方式允许每个阶段清楚的描述执行本阶段之前需要存在的前提条件,以及本阶段执行之后会存在的后置条件。
3. JSF请求处理生命周期各个阶段:
(1)恢复视图:
因为JSF组件是服务器端组件,可以认为客户端显示的用户界面其实是JSF组件提供的一个镜像。所以此阶段的任务是根据前一个事物恢复现有视图,或者根据新请求创建新视图。如果是新请求,就创建新视图,并保存在父容器对象FacesContext内。
(2)应用请求值:
此阶段主要是对进入的请求值或名称-值对进行处理。即在用户界面组件视图(或UIViewRoot)上调用高级方法processDecodes(),把请求值应用到用户界面组件(所有子组件都会递归调用它们的processDecodes(),进行请求名称-值对的“解码”,把匹配的新值应用到用户界面组件的value属性)。注意一点的是,只有能容纳值的用户界面组件(如:InputText)才有新值应用到它们。
这里有个概念可能对以后会有帮助:所有具有value属性的组件都实现valueHolder接口。所有表单元素类型组件,如果它的值可以由用户编辑,那么就都实现了EditableValueHolder接口。所有引起动作的组件(按钮或连接)都实现ActionSource接口(对于JSF1.2动作组件实现的是ActionSource2接口,它允许使用1.2中新的统一EL)。
对于按钮在表单提交期间,不用更新新值,它只需记住自己是否被单击,如果单击就引起动作事件并进入事件队列中。
还要注意的是: JSF请求处理生命周期使用连贯的方式处理不同阶段,但阶段的执行顺序可以为特殊情况而变化。比如把组件的immediate属性设置为true,就会跳过所有验证,不处理表单的值,直接导航到另一页。当然不同的组件上设置immediate属性会有不同的效果。(大家可以自己动手做些实例)
(3) 处理验证:
处理完应用请求值后,就要执行对进入数据的转换和验证了。在这个阶段主要是调用processValidators()。即每个子组件都递归的执行此方法(和processDecodes()类似)
注意的是:数据类型的转换实际发生在验证之前,因为要验证必须先把数据转换成服务器端数据类型。
如果这个阶段出现错误,将会把FacesMessages消息放进FacesContext队列。当响应被渲染回用户,可以见到Message或Messages组件显示的消息。
(4) 更新模型值:
到这个阶段后,将把通过转换和验证的数据分配给值绑定到用户界面组件的模型对象。
这里的意思是:如果你有一个代表用户的JAVA类User,把它注册为托管bean,并用JSF表达式语言把属性绑定到页面上的不同用户界面组件,那么在这个阶段,实际的托管bean或模型对象的属性,被他们绑定的用户界面组件的新值更新。假如你在inputText组件中输入username(并且通过上面3个阶段)那么现在你在inputText中的值为username,此时你的User类的name属性也为username.(大家做实例去 体会吧)。
此阶段其实和其他阶段类似:在UIViewRoot上调用processUpdates()方法,对每个子组件都递归执行此方法。在这里如果存在类型为UIInput或者它的扩展组件就会调用updateModel()方法。其实这里揭示了一个秘密:只要把JavaBean属性绑定到一组JSF用户界面组件,就不需要手动编码,他们能自动更新。
(5) 调用应用程序:
这个部分是真正对取得的数据进行操作的阶段。
用户界面组件可以容纳值(实现EditableValueHolder)也可以是AcionEvent来源(实现ActionSource),即动作方法或动作侦听器就是在此阶段调用的。
在此阶段,UIViewRoot的processApplication()方法被调用,它又把队列中这个阶段的事件广播到每个实现ActionSrouce(JSF1.2ActionSrouce2)的UIComponent组件。这通过调用每个UIComponent的broadcast()方法做到的,实际上就触发了动作事件,接着由动作侦听器处理这些动作事件。可用默认动作侦听器编写定制动作方法或动作侦听器方法并绑定到UIComponent(实现了ActionSource的UIComponent)处理动作事件。
(6) 渲染响应:
在这个阶段,为了把整个响应渲染回客户端,将逐一对每个组件递归调用encodeXX()方法。
处理把响应渲染给客户端,渲染响应阶段还保存视图的当前状态,以便可以在后续web请求中访问恢复状态
其实在JSF1.2,渲染响应阶段被重新设计了,大家可以通过实例来感受下<f:verbatim>在1.1和1.2中添加和不添加f:verbatim<f:verbatim></f:verbatim>有什么变化。
现在渲染就先说到这里
这些只是幕后的工作,对于一般的人知道有这个概念就可以了,而对于想理解JSF高级特性的人来说(比如编写AJAX的JSF组件), JSF请求处理生命周期显得很重要,不过在刚看后不要着急自己是否弄懂了,在实践中体会比纸上谈兵更容易理解。希望大家在日后使用JSF的过程中一边做一边去联系下 JSF请求处理生命周期。会有很大收获的。</f:verbatim>