JSF规范,Standard Request Processing Lifecycle Phases
尝试翻译了一下JSF12规范中关于6大处理过程的内容,有些地方不太明确.不过感觉对JSF的了解还是有一定帮助.自学用.
Standard Request Processing Lifecycle Phases
The standard phases of the request processing lifecycle are described in the following subsections.
1 Restore View
The JSF implementation must perform the following tasks during the Restore View phase of the request processing lifecycle:
在请求处理生命周期的Restore View阶段中,JSF实现必须执行以下任务:
■ Call initView() on the ViewHandler. This will set the character encoding properly for this request.
在ViewHandler中调用initView()。为当前请求设置编码属性。
■ Examine the FacesContext instance for the current request. If it already contains a UIViewRoot:
检测当前请求的FacesContext。如果已包含UIViewRoot,则:
■ Set the locale on this UIViewRoot to the value returned by the
getRequestLocale() method on the ExternalContext for this request.
在UIViewRoot上为当前请求设置本地信息,由ExternalContext的getRequestLocale()方法获取该值。
■ For each component in the component tree, determine if a ValueExpression for “binding” is present. If so, call the setValue() method on this ValueExpression, passing the component instance on which it was found.
对于组件树中的每个组件,要确定是否出现ValueExpression的“bingding”属性。如果有则调用ValueExpression的setValue()方法,传递该组建实例(作为参数?)。
■ Take no further action during this phase, and return. The presence of a UIViewRoot already installed in the FacesContext before the Restore View Phase implementation indicates that the phase should assume the view has already been restored by other means.
在此阶段无进一步的行为,则返回。在Restore View 阶段前,出现的UIViewRoot已安置在FacesContext中,JSf实现应当使当前view已经被其他方式重建。
■ Determine if this request is a postback or initial request by executing the following algorithm. Find the render-kit-id for the current request by calling calculateRenderKitId() on the Application’s ViewHandler. Get that RenderKit’s ResponseStateManager and call its isPostback() method, passing the current FacesContext.
可以通过以下算法确定请求是postback还是initial请求。通过调用Application’s ViewHandler的calculateRenderKitId()方法查找当前请求的render-kit-id。获得render-kit-id相应的RenderKit’s ResponseStateManager,调用isPostback()方法确定请求方式,同时传递FacesContext作为参数。
■ A request that is a non-postback request must call FacesContext.renderResponse() to cause intervening phases to be skipped.
非postback(初始)请求必须调用FacesContext.renderResponse()以跳过中间阶段。
■ If the request is a postback, call ViewHandler.restoreView(), passing the FacesContext instance for the current request and the view identifier, and returning a UIViewRoot for the restored view. If the return from ViewHandler.restoreView() is null, throw a ViewExpiredException with an appropriate error message.
javax.faces.application.ViewExpiredException is a FacesException
that must be thrown to signal to the application that the expected view was not returned for the view identifier. An application may choose to perform some action based on this exception.
如果是postback请求,调用ViewHandler.restoreView(),传递当前FacesContext实例和view ID标示作为参数,返回UIViewRoot作为重建view。如果返回null,则抛出相应错误信息的ViewExpiredException异常。javax.faces.application.ViewExpiredException用来表示应用未返回view ID标示相应的view。基于这样的异常,应用可采取相应的措施。
■ For each component in the component tree, determine if a ValueExpression for “binding” is present. If so, call the setValue() method on this ValueExpression, passing the component instance on which it was found. Do this in a “parent-first” fashion, calling the setValue() method and then traversing the children.
对于组件树中的每个组件,确定ValueExpression的“bingding”是否出现 。如果有则调用setValue()方法,传递该组件实例作为参数。以“父节点优先”的方式调用setValue()方法,并遍历所有子节点。
■ If the request is a non-postback, call ViewHandler.createView(), passing the FacesContext instance for the current request and the view identifier.
如果为non-postback请求,则以当前请求的FaceContext实例和view Id标示为参数,调用ViewHandler.createView()方法,(创建新的viewRoot)。
■ Store the restored or created UIViewRoot in the FacesContext.
At the end of this phase, the viewRoot property of the FacesContext instance for the current request will reflect the saved configuration of the view generated by the previous Faces Response, or a new view returned by ViewHandler.createView() for the view identifier.
The implementation for this phase must not derive a new view identifier based on the servlet mapping. This must be delegated to the default ViewHandler implementation. See Section 7.5.2 “Default ViewHandler Implementation”.
在FaceContext中存储重建或新创建的UIViewRoot。
此阶段结束时,在当前请求的FacesContext实例中,viewRoot属性将用来表示view所需要保存的配置信息,view 可以由前一个Faces Response产生或由ViewHandler.createView()根据view ID产生。此阶段不能基于servlet mapping 产生view ID,必须委托给缺省的ViewHandler实现。
2 Apply Request Values
The purpose of the Apply Request Values phase of the request processing lifecycle is to give each component the opportunity to update its current state from the information included in the current request (parameters, headers, cookies, and so on). When the information from the current request has been examined to update the component’s current state, the component is said to have a “local value”.
请求处理生命周期中的Apply Request Values阶段的目的是,使组件有机会从当前请求的信息中获取所需值更新组件的当前状态。当前请求的信息被确认用来更新组件状态后,组件被认为拥有“local value”。
During the Apply Request Values phase, the JSF implementation must call the processDecodes() method of the UIViewRoot of the component tree. This will normally cause the processDecodes() method of each component in the tree to be called recursively, as described in the Javadocs for the UIComponent.processDecodes() method. For UIInput components, data conversion must occur as described in the UIInput Javadocs.
在Apply Request Values阶段,JSF实现必须调用组件树中UIViewRoot的processDecodes()方法。通常都会引起树中组件递归调用processDecodes()方法,见Javadocs中关于UIComponent.processDecodes()方法的描述。对于UIInput组件,必须产生数据转换,见javadocs中关于UIInput的描述。
During the decoding of request values, some components perform special processing, including:
■ Components that implement ActionSource (such as UICommand), which recognize that they were activated, will queue an ActionEvent. The event will be delivered at the end of Apply Request Values phase if the immediate property of the component is true, or at the end of Invoke Application phase if it is false.
在解码请求值时,一些组件有特殊的处理过程,包括:
实现了ActionSource接口的组件(如UICommand),当被激活(调用)时,将ActionEvent排入事件队列中。如果组件的“immediate”属性为“true”,则事件event会在Apply Request Values阶段结束时被传递,如果为”false”,则在Invoke Application 阶段结束时被传递。
■ Components that implement EditableValueHolder (such as UIInput), and whose immediate property is set to true, will cause the conversion and validation processing (including the potential to fire ValueChangeEvent events) that normally happens during Process Validations phase to occur during Apply Request Values phase instead.
As described in Section 2.3 “Common Event Processing”, the processDecodes() method on the UIViewRoot component at the root of the component tree will have caused any queued events to be broadcast to interested listeners.
实现了EditableValueHolder接口的组件,如果immediate属性为true,则通常在Process Validations阶段才会发生的转换和验证处理(包括可能触发ValueChangeEvent事件),将发生在Apply Request Values阶段。
At the end of this phase, all EditableValueHolder components in the component tree will have been updated with new submitted values included in this request (or enough data to reproduce incorrect input will have been stored, if there were conversion errors).
In addition,conversion and validation will have been performed on EditableValueHolder components whose immediate property is set to true. Conversions and validations that failed will have caused messages to be enqueued via calls to the addMessage() method of the FacesContext instance for the current request, and the valid property on the corresponding component(s) will be set to false.
在此阶段结束时,组件树中的所有EditableValueHolder组件都会以请求中新提交的值更新(如果发生转换错误,也应该保存足够的信息以从新产生(恢复)原来不正确的输入)。此外,对于immediate属性为true的EditableValueHolder组件将实现数据转换和验证。如果装换和验证失败,通过调用当前请求FacesContext实例的addMessage()方法将错误信息排入队列中,并将该组件的valid属性设置为false。
If any of the decode() methods that were invoked, or an event listener that processed a queued event, called responseComplete() on the FacesContext instance for the current request, clear the remaining events from the event queue and terminate lifecycle processing of the current request. If any of the decode() methods that were invoked, or an event listener that processed a queued event, called renderResponse() on the FacesContext instance for the current request, clear the remaining events from the event queue and transfer control to the Render Response phase of the request processing lifecycle. Otherwise, control must proceed to the Process Validations phase.
当调用任何decode()方法或事件监听器处理队列中的事件时,只要当前请求的FacesContext实例的responseComplete()方法被调用,则清除事件队列中的剩余事件并结束当前请求处理的生命周期。
当调用任何decode()方法或事件监听器处理队列中的事件时,只要当前请求的FacesContext实例的renderResponse()方法被调用,则清除事件队列中的剩余事件并跳转到请求处理生命周期的Render Response阶段。
否则必须处理 Process Validations阶段。
3 Process Validations
As part of the creation of the view for this request, zero or more Validator instances may have been registered for each component. In addition, component classes themselves may implement validation logic in their validate() methods. During the Process Validations phase of the request processing lifecycle, the JSF implementation must call the processValidators() method of the UIViewRoot of the tree. This will normally cause the processValidators() method of each component in the tree to be called recursively, as described in the API reference for the UIComponent.processValidators() method.
作为为当前请求创建view的一部分,每个组件都可能已经注册了0个或多个Validator验证器实例。此外,组建类自己也可以通过validate()方法实现验证逻辑。在请求处理生命周期的Process Validations阶段中,JSF实现必须调用组件树中UIViewRoot的processValidator()方法。这通常都会引起树中组件递归调用processValidator ()方法,见API参考中UIComponent.processValidators()方法的描述。
Note that EditableValueHolder components whose immediate property is set to true will have had their conversion and validation processing performed during Apply Request Values phase.
注意,对于EditableValueHolder组件,如果它的immediate属性为true,那么转换和验证会在Apply Request Values阶段进行。
During the processing of validations, events may have been queued by the components and/or Validators whose validate() method was invoked. As described in Section 2.3 “Common Event Processing”, the processValidators() method on the UIViewRoot component at the root of the component tree will have caused any queued events to be broadcast to interested listeners.
在处理验证时,组件中的队列事件和/或验证器Validators的validate()方法被调用。如“Common Event Processing”所述,组件树的根节点UIViewRoot组件的processValidators()方法将把队列中的事件广播给相关事件监听者。
At the end of this phase, all conversions and configured validations will have been completed. Conversions and Validations that failed will have caused messages to be enqueued via calls to the addMessage() method of the FacesContext instance for the current request, and the valid property on the corresponding components will have been set to false.
If any of the validate() methods that were invoked, or an event listener that processed a queued event, called responseComplete() on the FacesContext instance for the current request, clear the remaining events from the event queue and terminate lifecycle processing of the current request. If any of the validate() methods that were invoked, or an event listener that processed a queued event, called renderResponse() on the FacesContext instance for the current request, clear the remaining events from the event queue and transfer control to the Render Response phase of the request processing lifecycle.
Otherwise, control must proceed to the Update Model Values phase.
在此阶段结束时,所有的转换和配置的验证都将完成。转换器和验证器的失效,将通过调用当前请求FacesContext实例的addMessage()方法把错误信息排入队列中,并将该组件的valid属性设置为false。
当调用任何validate ()方法或事件监听器处理队列中的事件时,只要当前请求的FacesContext实例的responseComplete()方法被调用,则清除事件队列中的剩余事件并结束当前请求处理的生命周期。
当调用任何validate ()方法或事件监听器处理队列中的事件时,只要当前请求的FacesContext实例的renderResponse()方法被调用,则清除事件队列中的剩余事件并跳转到请求处理生命周期的Render Response阶段。
否则必须处理 Update Model Values阶段。
4 Update Model Values
If this phase of the request processing lifecycle is reached, it is assumed that the incoming request is syntactically and semantically valid (according to the validations that were performed), that the local value of every component in the component tree has been updated, and that it is now appropriate to update the application's model data in preparation for performing any application events that have been enqueued.
如果请求处理生命周期到达这个阶段,可以认为到达的请求在语法和语义上是有效的(由于进行了验证处理),组件树中每个组件的local value已被更新,此时适合更新应用模型数据为处理队列中的应用事件做准备。
During the Update Model Values phase, the JSF implementation must call the processUpdates() method of the UIViewRoot component of the tree. This will normally cause the processUpdates() method of each component in the tree to be called recursively, as described in the API reference for the UIComponent.processUpdates() method.
The actual model update for a particular component is done in the updateModel() method for that component. During the processing of model updates, events may have been queued by the components whose updateModel() method was invoked. As described in Section 2.3 “Common Event Processing”, the processUpdates() method on the UIViewRoot component at the root of the component tree will have caused any queued events to be broadcast to interested listeners.
在处理Update Model Values阶段,JSF实现必须调用组件树中UIViewRoot的processUpdates ()方法。这通常都会引起树中组件递归调用processUpdates ()方法,见API参考中UIComponent. processUpdates ()方法的描述。
特定组件的模型数据更新,通过组建的updateModel()方法实现。在处理模型更新过程中,被组件排入队列中的事件也会调用updateModel()方法。如“Common Event Processing”所述,组件树的根节点UIViewRoot组件的processUpdates ()方法将把队列中的所有事件广播给相关事件监听者。
At the end of this phase, all appropriate model data objects will have had their values updated to match the local value of the corresponding component, and the component local values will have been cleared.
If any of the updateModel() methods that were invoked, or an event listener that processed a queued event, called responseComplete() on the FacesContext instance for the current request, clear the remaining events from the event queue and terminate lifecycle processing of the current request. If any of the updateModel() methods that was invoked, or an event listener that processed a queued event, called renderResponse() on the FacesContext instance for the current request, clear the remaining events from the event queue and transfer control to the Render Response phase of the request processing lifecycle. Otherwise, control must proceed to the Invoke Application phase.
在此阶段结束时,所有相应的模型数据都应该已经根据组件的local value进行了更新,并且组件的local values将被清除。
当调用任何updateModel ()方法或事件监听器处理队列中的事件时,只要当前请求的FacesContext实例的responseComplete()方法被调用,则清除事件队列中的剩余事件并结束当前请求处理的生命周期。
当调用任何updateModel ()方法或事件监听器处理队列中的事件时,只要当前请求的FacesContext实例的renderResponse()方法被调用,则清除事件队列中的剩余事件并跳转到请求处理生命周期的Render Response阶段。
否则必须处理 Invoke Application phase阶段。
5 Invoke Application
If this phase of the request processing lifecycle is reached, it is assumed that all model updates have been completed, and any remaining event broadcast to the application needs to be performed. The implementation must ensure that the processApplication() method of the UIViewRoot instance is called. The default behavior of this method will be to broadcast any queued events that specify a phase identifier of PhaseId.INVOKE_APPLICATION. If responseComplete()was called on the
FacesContext instance for the current request, clear the remaining events from the event queue and terminate lifecycle processing of the current request. If renderResponse() was called on the FacesContext instance for the current request, clear the remaining
events from the event queue.
Advanced applications (or application frameworks) may replace the default ActionListener instance by calling the setActionListener() method on the Application instance for this application. However, the JSF implementation must provide a default ActionListener instance that behaves as described in Section 7.1.1
“ActionListener Property”.
到请求处理生命周期的这个阶段,则认为完成了所有模型的数据更新,需要对该应用的所有剩余事件执行广播。该(JSF)实现必须确保UIViewRoot实例的processApplication()方法被调用。该方法的缺省行为是去广播队列事件中所有phase ID标示为PhaseId.INVOKE_APPLICATION的事件。
如果当前请求的FacesContext实例的responseComplete()方法被调用, 则清除事件队列中的剩余事件并结束当前请求处理的生命周期。
如果当前请求的FacesContext实例的renderResponse()方法被调用,则清除事件队列中的剩余事件。
复杂应用可以通过调用该应用实例的setActionListener()方法,替换缺省的ActionListener实例。但JSF实现必须提供缺省的ActionListener实例以提供“ActionListener Property”中所描述的行为。
6 Render Response
This phase accomplishes two things:
1. Causes the response to be rendered to the client
2. Causes the state of the response to be saved for processing on subsequent requests.
The reason for bundling both of these responsibilities into this phase is that in JSP applications, the act of rendering the response may cause the view to be built, as the page renders. Thus, we can’t save the state until the view is built, and we have to save the state
before sending the response to the client to enable saving the state in the client.
此阶段完成两件事:
1、 将响应渲染到客户端。
2、 为处理后续请求,保存响应状态。
之所以在这个阶段绑定这两个行为,是因为在JSP应用中,响应的渲染行为将导致view的构建,以作为页面渲染(重绘)。这样在构建view前不能保存状态,所以不得不在发送响应到客户端前保存,以便能将状态保存在客户端。
JSF supports a range of approaches that JSF implementations may utilize in creating the response text that corresponds to the contents of the response view, including:
■ Deriving all of the response content directly from the results of the encoding methods (on either the components or the corresponding renderers) that are called.
■ Interleaving the results of component encoding with content that is dynamically generated by application programming logic.
■ Interleaving the results of component encoding with content that is copied from a static “template” resource.
■ Interleaving the results of component encoding by embedding calls to the encoding methods into a dynamic resource (such as representing the components as custom tags in a JSP page).
Because of the number of possible options, the mechanism for implementing the Render Response phase cannot be specified precisely.
JSF实现可以利用许多方式创建与应响view内容相对应的响应文本。包括:
■ 直接调用(组件或渲染器的)编码方法产生所有响应内容 。
■ 结合应用编程逻辑动态产生的编码内容,组合成组件的响应内容。
■ 结合静态“模板”资源的拷贝内容,组合成组件的响应内容。
■ 结合嵌入的方法调用产生动态资源(如在JSP页面中,将组件表示为自定义标签),组合成响应内容。
由于有很多可选方法,不能明确指定Render Response阶段的实现方法。
However, all JSF implementations of this phase must conform to the following requirements:
■ JSF implementations must provide a default ViewHandler implementation that performs a RequestDispatcher.forward() call to a web application resource whose path is equal to the view identifier of the component tree.
■ If all of the response content is being derived from the encoding methods of the component or associated Renderers, the component tree should be walked in the same depth-first manner as was used in earlier phases to process the component tree, but subject to the additional constraints listed here.
■ If the response content is being interleaved from additional sources and the encoding methods, the components may be selected for rendering in any desired order(Typically, component selection will be driven by the occurrence of special markup (such as the existence of a JSP custom tag) in the template text associated with the component tree).
■ During the rendering process, additional components may be added to the component tree based on information available to the ViewHandler implementation(For example, this technique is used when custom tags in JSP pages are utilized as the rendering technology, as described).
但所有的JSF实现都必须遵循以下条件:
■ JSF实现必须提供缺省ViewHandler实现,通过执行RequestDispatcher.forward()调用Web应用资源,其路径和组件树中的view ID标示相同(?)。
■ 如果所有的响应内容都由组件或相关渲染器的编码方法产生,则组件树应当以之前各阶段采取的深度优先方式遍历组件树,但因遵循这里列出的附加条件。
■ 如果响应内容插入了另外的资源和编码方法,则组件可以选择任意需要的渲染顺序。?
■ 在渲染过程中,需要添加的组件可以根据提供给ViewHandler实现的有效信息,添加到组件树中。
However, before adding a new component, the ViewHandler implementation must first check for the existence of the corresponding component in the component tree. If the component already exists (perhaps because a previous phase has pre-created one or more components), the existing component’s properties and attributes must be utilized.
但在添加新组件前,ViewHandler实现必须首先检查组件树中是否已存在相应的组件。如果组件已经存在(也许前面已经创建了一个或多个组件),已存在的组件(属性)信息必须可以被利用。
■ Under no circumstances should a component be selected for rendering when its parent component, or any of its ancestors in the component tree, has its rendersChildren property set to true. In such cases, the parent or ancestor component must render the content of this child component when the parent or ancestor was selected.
■ 当组件被渲染时,其父组件或任意祖先组件的rendersChildren的属性一定被置成true。在此条件下,当渲染父组件或祖先组件时,必须渲染子组件内容。
■ If the isRendered() method of a component returns false, the renderer for that component must not generate any markup, and none of its facets or children (if any) should be rendered.
如果isRendered()方法返回false,组建不会渲染任何标记,其任意片段(facets)或子组件(如果存在)都不应被渲染。
■ It must be possible for the application to programmatically modify the component tree at any time during the request processing lifecycle (except during the rendering of the view) and have the system behave as expected.
For example, the following must be permitted.
Modification of the view during rendering may lead to undefined results. It must be possible to allow components added by the templating system (such as JSP) to be removed from the tree before rendering.
It must be possible to programmatically add components to the tree and have them render in the proper place in the hierarchy.
It must be possible to re-order components in the tree before rendering. These manipulations do require that any components added to the tree have ids that are unique within the scope of the closest parent NamingContainer component.
The value of the rendersChildren property is handled as expected, and may be either true or false.
在任何请求处理的生命周期中(除在渲染view的过程中),应用都可以通过程序改变组件树并使系统产生预期的行为。
例如必须允许以下操作。
在渲染过程中修改view会导致未定义结果。
在渲染前,通过模板系统(如JSP)添加的组件一定可以从组件树中移除。
一定可以通过编程方式将组件添加到组件树中,并在层次结构的适当位置渲染组件。
渲染前,一定可以将组件树中的组件重新排序。
这些操作都需要满足,任意添加到组件树中的组件都有唯一的ID,在最近一层父NamingContainer组件范围内唯一。
rendersChildren属性应该被正确设置成预期的true或false。
When each particular component in the component tree is selected for rendering, calls to its encodeXxx() methods must be performed in the manner described in Section 3.1.12 “Component Specialization Methods”. For components that implement ValueHolder (such as UIInput and UIOutput), data conversion must occur as described in the UIOutput Javadocs.
当组件树中被选中渲染的指定组件调用它的encodeXxx()方法时,必须以“Component Specialization Methods”中描述的方式执行。对于实现了ValueHolder接口(如UIInput和UIOutput)的组件,必须以Javadocs 中 UIOutput描述的方式执行数据转换。
Upon completion of rendering, the completed state of the view must have been saved using the methods of the class StateManager. This state information must be made accessible on a subsequent request, so that the Restore View can access it. For more on StateManager, see Section 7.6.3 “State Saving Methods.”
当渲染完成时,必须由类StateManager的方法保存view的已完成状态。在后续请求中这种状态信息可以被访问,使得Restore View阶段能访问该状态信息。
--转自
该贴由system转至本版2014-10-30 23:18:05