当一个组件树在一个postbacks请求中被恢复之后其中每个组件从request的参数中取得各自的值,这里使用的是processDecodes方法。这个值会保存在本地的每个组件中,在源码中此过程的代码较为简单,因为实现者将取值这个操作全部封装在processDecodes方法中。不过说实话JSF的这部分的实现非常失败,因为在UIViewRoot中有将近两千行代码,这,这,这……
(UIViewRoot.java中的processDecodes方法)
public void processDecodes(FacesContext context) { initState(); notifyBefore(context, PhaseId.APPLY_REQUEST_VALUES); try { if (!skipPhase) { if (context.getPartialViewContext().isPartialRequest() && !context.getPartialViewContext().isExecuteAll()) { context.getPartialViewContext().processPartial(PhaseId.APPLY_REQUEST_VALUES); } else { super.processDecodes(context); } broadcastEvents(context, PhaseId.APPLY_REQUEST_VALUES); } } finally { clearFacesEvents(context); notifyAfter(context, PhaseId.APPLY_REQUEST_VALUES); } }
如果任何一个解码方法或者监听器的事件调用当前FacesContext实例中的renderResponse方法。JSF的实现者会跳过 Render Response步骤。其实这很好理解在处理组件所需要的值的时候如果遇到错误就会直接渲染页面向用户进行提示。但是笔者在JSF源码中还未找到这部分的实现(衰~)
如果任何的事件在此步骤中加进队列JSF会将这个事件传递给相关的监听器。
如果页面上的一些组件中的immediate属性设置为true那么验证,转化以及事件绑定将都会在这个步骤中进行,如果任何转换失败这个组件会产生一个错误的提示信息。并将这个信息放到FacesContext的显示队列中。这个信息将会在Render Response步骤中显示出来,同理在验证步骤中的验证错误信息也会如此显示出来。
这时如果程序需要重定向到不同的应用资源或者要产生一个响应,并且这个响应没有包含任何JSF组件,那么就直接调用FacesContext.responseComplete方法。
在这个步骤的最后组件将会被赋予新的值,并且消息以及时间将会被放到队列当中等待处理。
如果当前请求被定义为一个局部的请求,那么局部内容会被从FacesContext中恢复,而且局部处理方法会被执行。
上面的每一个段话都是说的在此阶段要处理得各种不同的情况,或者说都是在processDecodes方法中应该考虑到的各个情况,Apply Request Values Phase一言以蔽之:拿值!