JSF请求处置过程中可以看到对于每一个phase都调用了doPhas方法,最后。同时把LifeCycl和FacesContext当做参数传入了值得注意的所谓的phaseListen也传入了phasedoPhas方法中,由此大约能够想明白这个“阶段监听器”道理了
web.xml里面配置了一个Servlet叫做javax.faces.webapp.FacesServlet于是可以知道,JSF应用中。检查、解一个请求的处置过程可以从这里开始。从官方网站上下载JSF源代码,项目名比较古怪,叫做“mojarra看的版本是1.2_12_b01里面包括了两个子项目,一个是jsf-api里面大多是接口以及少量关键类。另外一个项目叫做jsf-ri对着这个"ri"邪念了半天之后,终于在兄弟提醒之下想明白了referimplement意思。jsf-apiJavaEE规范的一部分,里面的类型包名都是以javax.fac开头的而jsf-ri项目是sun针对JSF规范的一个参考实现,里面的类型的包名都是以com.sun.fac开头的
FacesServlet初始化(FacesServlet#init:系统启动的时候,JSF请求处置过程中。会初始化FacesServlet调用其中的init方法。里面主要做了两件事情,一个是初始化FacesContextFactori另外一个是初始化Lifecycl对象。jsf-api项目中,FacesServlet类是一个Servlet接口的实现类,而FacesContextFactori和Lifecycl都是接口。jsf-ri项目中有这两个接口的实现类,分别是com.sun.faces.context.FacesContextFactoryImpl和com.sun.faces.lifecycle.LifecycleImpl类。
一个想当然的事实: FacesServlet初始化的时候要根据一些配置来判断具体的FacesContextFactori和Lifecycl实现类是什么,也就是这里,JSF规范”和“JSF实现”接轨了想来MyFac等等的其他JSF实现应该不外乎两种方式,一种是改变FacesServletinit方法中需要用到配置的值,于是启用自己的FacesContextFactori实现和Lifecycl实现,后面的处置过程就全部走自己的逻辑了第二种方法笨一点,可能性不大,就是把FacesServlet覆盖替换掉,其中也不需要读什么配置了直接使用自己的实现类即可—不过这种做法估计不符合JSF规范,想来只有我等虾米民众能做的进去。主要代码如下:
facesContextFactori=FacesContextFactoriFactoryFinder.
getFactoriFactoryFinder.FA CES_CONTEXT_FA CTORY;
3LifecycleFactorilifecycleFactori=LifecycleFactoriFactoryFinder.
getFactoriFactoryFinder.LIFECYCLE_FA CTORY;
FacesContextFactori很明显是用来生产FacesContext这么个东西的而FacesContext可以看做是一个RequestWrapp注意这个FaceContext和ServletContext不一样,ServletContext一个Web应用只有一个的全局对象,对应的一个Webapplic而一个FacesContext对应的一个request,回头再来看初始化的结果。另外,RequestWrapp这个说法不严格,实际上FacesContext里面也包装了ServletContextRespons等)而LifeCycl可以看做是一个过滤器链(类似于servlet规范里面的FilterChain于是整个JSF请求处置过程,实际上就是包装成为FaceContext用户请求,通过类似于一个FilterChainLifeCycl过程。
很明显是看FacesServletservic方法。FacesServlet初始化过程中,这总览。构造出了全局的FacesContextFactori对象和LifeCycl对象。可以把FacesContextFactori看做是一个“请求包装工厂”于是很明显,每当一个请求到达FacesServlet时候,第一步便是拿着请求,包装工厂里面包装一下,而包装的结果就是一个FacesContext代码如下:
request,FacesContextcontext=facesContextFactory.getFacesContextservletConfig.getServletContext.response,lifecycl;
实际上是创立了一个com.sun.faces.context.FacesContextImpl对象,包装过程中。FacesContextImpl类继承了jsf-api项目中的javax.faces.context.FacesContextFacesContextImpl构造方法的第一个参数是一个叫做ExternalContext接口的实现,检查其源代码,可以看到ExternalContextImpl类耦合了ServletAPI而FacesContextImpl与ServletAPI无关。实际上,这里,做到JSF可以不只仅使用在Servlet环境中,正如ExternalContext接口的注释中所说,Servlet环境中使用JSF和在Portlet环境中使用JSF不同,实际上就是使用了不同的ExternalContextFacesContextFactoryImpl中构造FacesContextImpl代码如下:
FacesContextctx=newFacesContextImpl
newExternalContextImplServletContextsc.
ServletResponsrespons, ServletRequestrequest.
lifecycl;
还做了另外一件事情,FacesContextImpl构造方法中。就是根据配置确定了RenderKitFactori显然不同的RenderKitFactori可以发生不同的RenderKit而不同RenderKit对象是针对不同客户端的所以对于浏览器、移动设备等等,会有不同的RenderKitFacesContextImpl构造方法中代码如下:
this.externalContext=ec;
setCurrentInstthi;
this.rkFactori=RenderKitFactoriFactoryFinder.getFactoriFactoryFinder.RENDER_KIT_FA CTORY;
实际上是FacesContext类里面有一个静态的ThreadLoc对象用来存放了当前请求线程对应的FacesContext对象,代码中我经常使用FacesContext.getCurrentInst这个静态方法来获取与当前请求对应的FacesContext对象。于是上面的代码中setCurrentInstthi就是把当前构造进去的这个FacesContext对象放到ThreadLoc里面。
正如上面所说,FacesContext创建进去以后。要让他经过LifeCycl这个“FilterChain逐步处置了那么,FilterChain里面放的一个一个Filter那么LifeCycl这个Chain里面放的什么呢?答案是Phase
分成了两个部分。一个部分是调用LifeCyclexecut方法,FacesServlet让FaceContext通过LifeCycl处置。执行逻辑,第二个部分是调用LifeCyclrender方法,呈现响应。FacesServlet.servic中代码如下:
lifecycle.executcontext;
lifecycle.rendcontext;
存放了一个Phase对象的数组,LifeCycleImpl这个实现中。存放了7个Phase其中第一个是null然后依次是视图重建、应用请求值、验证、更新模型值、执行应用顺序、呈现响应。execut方法中,调用了从视图重建开始到执行应用顺序为止的5个Phase而在render方法中,调用了最后一个Phase也就是呈现响应。LifeCycleImpl类中,代码如下:
//ThePhaseinstancfortherendermethod
privatPhaserespons=newRenderResponsePhas;
//ThesetofPhaseinstancthatarexecutbytheexecutmethod
//inorderbytheordinpropertiofeachphase
privatPhase[]phase={
//ANY_PHA SEplaceholder, null.notarealPhase
newRestoreViewPhas.
newApplyRequestValuesPhas.
newProcessValidationsPhas.
newUpdateModelValuesPhas.
newInvokeA pplicationPhas.
response
};
可以由每一个Filter来决定是否要调用下一个Filter从而决定是否让请求继续通过FilterChain中的后续Filter链式调用的过程。而在LifeCyclexecut方法中,ServletFilter中。用一个for循环顺序执行几个Phase每一个Phase执行完之后,都会检查FaceContext对象中是否设置了停止后续处置直接呈现响应的标志(renderRespons或者已经完成了响应无需后续处置也不需要经过呈现响应阶段了responseComplet如果标志为true那么就不再执行后续Phase
LifeCycleImplexecut方法主要代码如下:
len=phases.length-1;i<len;i++{//SkipANY_PHA SEplaceholder forinti=1.
ifcontext.getRenderRespons||
context.getResponseComplet{
break;
}
this, phases[i].doPhascontext.listeners.listIter;
}
也会检查FacesContextresponseComplet状态,LifeCyclrender方法中。如果为true那么就不再执行renderPhase于是此刻知道了自己所写的一些代码或者JSF库里面的一些代码中,调用FacesContextresponseComplet方法和renderRespons得作用原理。render方法主要代码如下:
if!context.getResponseComplet{
this, response.doPhascontext.listeners.listIter;
}
Phase这个概念、接口,另外注意。以及几个实现,都是jsf-ri项目中的而在jsf-api中不存在Phase这个概念。所以,LifeCyclJSF规范的内容,而通过几个Phase来处置请求这种实现是sun参考实现的做法。