JSF 请求之恢复视图(Restore View phase) 阶段

 JSF 除了事件处理之外,总共必须经过六个阶段:

         1、恢复视图阶段 Restore View Phase

         2、应用请求值阶段 Apply Request Value Phase

         3、验证阶段 Process Validation Phase

         4、更新模型值阶段 Update Model Values Phase

         5、调用应用程序阶段 Invoke Application Phase

         6、渲染阶段 Render Response Phase

      这六个阶段分别对应六个执行器 RestoreViewExecutor,ApplyRequestValuesExecutor,ProcessValidationsExecutor, UpdateModelValuesExecutor,InvokeApplicationExecutor,RenderResponseExecutor,且都与生命周期对象(LifecycleImpl)耦合。

        在此,主要先说下第一阶段,恢复视图阶段 Restore View Phase主要做了什么,起了什么作用?

        在项目中引入JSF的是javax.faces.webapp.FacesServlet类,其关联了javax.faces.lifecycle.Lifecycle,所以在JSF中生命周期的

        概念是非常重要的,一直贯穿一个请求的始终。而在LIfecycle的实现类LifecycleImpl中又关联了PhaseExecutor类(是一个数组),包括: RestoreViewExecutor、ApplyRequestValuesExecutor、ProcessValidationsExecutor、 UpdateModelValuesExecutor、 InvokeApplicationExecutor、RenderResponseExecutor,这六个类共同继承了PhaseExecutor。其中RenderResponseExecutor是作一个单独的属性进行关联的。

          

        接下来我们来先看一段RestoreViewExecutor类中的核心代码:  

[java]  view plain copy
  1.  public boolean execute(FacesContext facesContext)  
  2.     {  
  3.         if (facesContext == null)  
  4.         {  
  5.             throw new FacesException("FacesContext is null");  
  6.         }  
  7.   
  8.         // get some required Objects  
  9.         Application application = facesContext.getApplication();  
  10.         ViewHandler viewHandler = application.getViewHandler();  
  11.         UIViewRoot viewRoot = facesContext.getViewRoot();  
  12.         RestoreViewSupport restoreViewSupport = getRestoreViewSupport(facesContext);  
  13.   
  14.         // Examine the FacesContext instance for the current request. If it already contains a UIViewRoot  
  15.         if (viewRoot != null)  
  16.         {  
  17.             if (log.isLoggable(Level.FINEST))  
  18.             {  
  19.                 log.finest("View already exists in the FacesContext");  
  20.             }  
  21.               
  22.             // Set the locale on this UIViewRoot to the value returned by the getRequestLocale() method on the  
  23.             // ExternalContext for this request  
  24.             viewRoot.setLocale(facesContext.getExternalContext().getRequestLocale());  
  25.               
  26.             restoreViewSupport.processComponentBinding(facesContext, viewRoot);  
  27.               
  28.             // invoke the afterPhase MethodExpression of UIViewRoot  
  29.             _invokeViewRootAfterPhaseListener(facesContext);  
  30.               
  31.             return false;  
  32.         }  
  33. .......  

          首先在JSF上下文中寻找组件树(UIViewRoot),如果找到则说明视图已经存在于上下文中,这时主要做了以下几件事:

        1)、把当前请求的Lacale赋给组件树。

        2)、执行组件树与EL表达式的绑定。?

                在这里RestoreViewExecutor关联了RestoreViewSupport类,调用了该类的一个方法:processComponentBinding

         这个方法的主要作用是:

                在这个方法里依赖了component这个类,循环调用了这个类的visitTree(visitContext, new RestoreStateCallback());

        3)、 // invoke the afterPhase MethodExpression of UIViewRoot
                    _invokeViewRootAfterPhaseListener(facesContext); ?

        如果找不到呢,接着来看这段代码:

   

[java]  view plain copy
  1.  String viewId = restoreViewSupport.calculateViewId(facesContext);  
  2.   
  3. // Determine if the current request is an attempt by the   
  4. // servlet container to display an error page.  
  5. // If the request is an error page request, the servlet container  
  6. // is required to set the request parameter "javax.servlet.error.message".  
  7. final boolean errorPageRequest = facesContext.getExternalContext().getRequestMap()  
  8.                                          .get("javax.servlet.error.message") != null;  
  9.   
  10. // Determine if this request is a postback or an initial request.  
  11. // But if it is an error page request, do not treat it as a postback (since 2.0)  
  12. if (!errorPageRequest && restoreViewSupport.isPostback(facesContext))  
  13. // If the request is a postback  
  14.     if (log.isLoggable(Level.FINEST))  
  15.     {  
  16.         log.finest("Request is a postback");  
  17.     }  
  18.   
  19.     try  
  20.     {  
  21.         facesContext.setProcessingEvents(false);  
  22.         // call ViewHandler.restoreView(), passing the FacesContext instance for the current request and the   
  23.         // view identifier, and returning a UIViewRoot for the restored view.  
  24.         viewRoot = viewHandler.restoreView(facesContext, viewId);  
  25.         if (viewRoot == null)  
  26.         {  
  27.             // If the return from ViewHandler.restoreView() is null, throw a ViewExpiredException with an   
  28.             // appropriate error message.  
  29.             throw new ViewExpiredException("No saved view state could be found for the view identifier: "  
  30.                                            + viewId, viewId);  
  31.         }  
  32.           
  33.         // Store the restored UIViewRoot in the FacesContext.  
  34.         facesContext.setViewRoot(viewRoot);  
  35.     }  
  36.     finally  
  37.     {  
  38.         facesContext.setProcessingEvents(true);  
  39.     }  
  40.       
  41.     // Restore binding  
  42.     // See https://javaserverfaces-spec-public.dev.java.net/issues/show_bug.cgi?id=806  
  43.     restoreViewSupport.processComponentBinding(facesContext, viewRoot);  
  44. }  
  45. else  
  46. // If the request is a non-postback  
  47.     if (log.isLoggable(Level.FINEST))  
  48.     {  
  49.         log.finest("Request is not a postback. New UIViewRoot will be created");  
  50.     }  
  51.       
  52.     //viewHandler.deriveViewId(facesContext, viewId)  
  53.     //restoreViewSupport.deriveViewId(facesContext, viewId)  
  54.     ViewDeclarationLanguage vdl = viewHandler.getViewDeclarationLanguage(facesContext,   
  55.             viewHandler.deriveLogicalViewId(facesContext, viewId));  
  56.       
  57.     // viewHandler.deriveLogicalViewId() could trigger an InvalidViewIdException, which  
  58.     // it is handled internally sending a 404 error code set the response as complete.  
  59.     if (facesContext.getResponseComplete())  
  60.     {  
  61.         return true;  
  62.     }  
  63.       
  64.     if (vdl != null)  
  65.     {  
  66.         ViewMetadata metadata = vdl.getViewMetadata(facesContext, viewId);  
  67.           
  68.         Collection<UIViewParameter> viewParameters = null;  
  69.           
  70.         if (metadata != null)  
  71.         {  
  72.             viewRoot = metadata.createMetadataView(facesContext);  
  73.               
  74.             if (viewRoot != null)  
  75.             {  
  76.                 viewParameters = ViewMetadata.getViewParameters(viewRoot);  
  77.             }  
  78.             else if(facesContext.getResponseComplete())  
  79.             {  
  80.                 // this can happen if the current request is a debug request,  
  81.                 // in this case no further processing is necessary  
  82.                 return true;  
  83.             }  
  84.         }  
  85.   
  86.         // If viewParameters is not an empty collection DO NOT call renderResponse  
  87.         if ( !(viewParameters != null && !viewParameters.isEmpty()) )  
  88.         {  
  89.             // Call renderResponse() on the FacesContext.  
  90.             facesContext.renderResponse();  
  91.         }  
  92.     }  
  93.     else  
  94.     {  
  95.         // Call renderResponse  
  96.         facesContext.renderResponse();  
  97.     }  
  98.       
  99.     // viewRoot can be null here, if ...  
  100.     //   - we don't have a ViewDeclarationLanguage (e.g. when using facelets-1.x)  
  101.     //   - there is no view metadata or metadata.createMetadataView() returned null  
  102.     if (viewRoot == null)  
  103.     {  
  104.         // call ViewHandler.createView(), passing the FacesContext instance for the current request and   
  105.         // the view identifier  
  106.         viewRoot = viewHandler.createView(facesContext, viewId);  
  107.     }  
  108.       
  109.     // Subscribe the newly created UIViewRoot instance to the AfterAddToParent event, passing the   
  110.     // UIViewRoot instance itself as the listener.  
  111.     // -= Leonardo Uribe =- This line it is not necessary because it was  
  112.     // removed from jsf 2.0 section 2.2.1 when pass from EDR2 to Public Review   
  113.     // viewRoot.subscribeToEvent(PostAddToViewEvent.class, viewRoot);  
  114.       
  115.     // Store the new UIViewRoot instance in the FacesContext.  
  116.     facesContext.setViewRoot(viewRoot);  
  117.       
  118.     // Publish an AfterAddToParent event with the created UIViewRoot as the event source.  
  119.     application.publishEvent(facesContext, PostAddToViewEvent.class, viewRoot);  
  120. }  
  121.   
  122. // add the ErrorPageBean to the view map to fully support   
  123. // facelet error pages, if we are in ProjectStage Development  
  124. // and currently generating an error page  
  125. if (errorPageRequest && facesContext.isProjectStage(ProjectStage.Development))  
  126. {  
  127.     facesContext.getViewRoot().getViewMap()  
  128.             .put(ErrorPageWriter.ERROR_PAGE_BEAN_KEY, new ErrorPageWriter.ErrorPageBean());  
  129. }  
  130.   
  131. // invoke the afterPhase MethodExpression of UIViewRoot  
  132. _invokeViewRootAfterPhaseListener(facesContext);  
  133.   
  134. return false;  


           1、置ViewId

        2、判断是否是个错误页面请求

        3、如果这不是一个错误页面请求且是一个回传请求或者初始请求,

                         那就找出viewRoot并把它设置到facesContext?(viewHandler.restoreView(facesContext, viewId);)

          

        4、如果这不是一个回传请求:

              这边依赖于ViewHandler类生成了ViewDeclarationLanguage视图描述语言实例,

               如果这个实例不为空,则:用这个实例取得视图元数据

                             ViewMetadata metadata = vdl.getViewMetadata(facesContext, viewId);

                         再用视图元数据创建ViewRoot

                                 还用视图元数据取得视图参数viewParameter,如果有直接进入渲染环节

              如果这个视图描述语言实例为空,直接进入渲染环节。

             

               如果到这边viewRoot还是为空,则用viewHandler生成视图根目录。

                           viewRoot = viewHandler.createView(facesContext, viewId);(e.g. when using facelets-1.x)

               否则,把viewRoot设置到FacesContext中,

               Publish an AfterAddToParent event with the created UIViewRoot as the event source.

               // invoke the afterPhase MethodExpression of UIViewRoot

 

 

 

              FacesContext可以看做是一个RequestWrapper(注意这个FaceContext和ServletContext不一样,ServletContext是一个Web应用只有一个的全局对象,对应的是一个Web application,而一个FacesContext对应的是一个request,另外,RequestWrapper这个说法不严格,实际上FacesContext里面也包装了ServletContext、Response等)。而LifeCycle可以看做是一个过滤器链(类似于servlet规范里面的Filter Chain)。于是,整个JSF请求处理过程,实际上就是包装成为FaceContext的用户请求,通过类似于一个Filter Chain的LifeCycle的过程。

              

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值