javascript

位置:IT落伍者 >> javascript >> 浏览文章

JSF请求处理过程(二) 请求处理过程总览


发布日期:2018年09月20日
 
JSF请求处理过程(二) 请求处理过程总览

请求处理过程总览(FacesServlet#service)

这总览很明显是看FacesServlet的service方法在FacesServlet的初始化过程中构造出了全局的FacesContextFactory对象和LifeCycle对象可以把FacesContextFactory看做是一个请求包装工厂于是很明显每当一个请求到达FacesServlet的时候第一步便是拿着请求到包装工厂里面包装一下而包装的结果就是一个FacesContext代码如下

FacesContext context = facesContextFactorygetFacesContext(servletConfiggetServletContext() request response lifecycle)

在包装过程中实际上是创建了一个ntextFacesContextImpl对象FacesContextImpl类继承了jsfapi项目中的ntextFacesContextFacesContextImpl的构造方法的第一个参数是一个叫做ExternalContext的接口的实现查看其源代码可以看到ExternalContextImpl类耦合了Servlet API而FacesContextImpl与Servlet API无关实际上在这里做到了JSF可以不仅仅使用在Servlet环境中正如ExternalContext接口的注释中所说在Servlet环境中使用JSF和在Portlet环境中使用JSF的不同实际上就是使用了不同的ExternalContext在FacesContextFactoryImpl中构造FacesContextImpl的代码如下

FacesContext ctx = new FacesContextImpl(new ExternalContextImpl((ServletContext) sc(ServletRequest) request(ServletResponse) response)lifecycle);

FacesContextImpl的构造方法中还做了另外一件事情就是根据配置确定了RenderKitFactory显然不同的RenderKitFactory可以产生不同的RenderKit而不同RenderKit对象是针对不同客户端的所以对于浏览器移动设备等等会有不同的RenderKitFacesContextImpl的构造方法中代码如下

thisexternalContext = ec;

setCurrentInstance(this);

thisrkFactory = (RenderKitFactory)FactoryFindergetFactory(FactoryFinderRENDER_KIT_FACTORY);

在代码中我们经常使用FacesContextgetCurrentInstance()这个静态方法来获取与当前请求对应的FacesContext对象实际上是在FacesContext类里面有一个静态的ThreadLocal对象用来存放了当前请求线程对应的FacesContext对象于是上面的代码中setCurrentInstance(this)就是把当前构造出来的这个FacesContext对象放到了ThreadLocal里面

FacesContext创建出来以后正如上面所说要让他经过LifeCycle这个Filter Chain的逐步处理了那么Filter Chain里面放的是一个一个Filter那么LifeCycle这个Chain里面放的是什么呢?答案是Phases

FacesServlet让FaceContext通过LifeCycle的处理分成了两个部分一个部分是调用LifeCycle的execute方法执行逻辑第二个部分是调用LifeCycle的render方法呈现响应FacesServletservice中代码如下

lifecycleexecute(context);

lifecyclerender(context);

在LifeCycleImpl这个实现中存放了一个Phase对象的数组存放了个Phase其中第一个是null然后依次是视图重建应用请求值验证更新模型值执行应用程序呈现响应在execute方法中调用了从视图重建开始到执行应用程序为止的个Phase而在render方法中调用了最后一个Phase也就是呈现响应在LifeCycleImpl类中代码如下

//The Phase instance for the render() method

private Phase response = new RenderResponsePhase();

// The set of Phase instances that are executed by the execute() method

// in order by the ordinal property of each phase

private Phase[] phases = {

null // ANY_PHASE placeholder not a real Phase

new RestoreViewPhase()

new ApplyRequestValuesPhase()

new ProcessValidationsPhase()

new UpdateModelValuesPhase()

new InvokeApplicationPhase()

response

};

在Servlet Filter中可以由每一个Filter来决定是否要调用下一个Filter从而决定是否让请求继续通过Filter Chains中的后续Filter是链式调用的过程而在LifeCycle的execute方法中是用一个for循环顺序执行几个Phase在每一个Phase执行完之后都会检查FaceContext对象中是否设置了停止后续处理直接呈现响应的标志(renderResponse)或者已经完成了响应无需后续处理也不需要经过呈现响应阶段了(responseComplete)如果标志为true那么就不再执行后续Phase

LifeCycleImpl的execute方法主要代码如下

for (int i = len = phaseslength ; i < len; i++) { // Skip ANY_PHASE placeholder

if (contextgetRenderResponse() ||

contextgetResponseComplete()) {

break;

}

phases[i]doPhase(context this listenerslistIterator());

}

在LifeCycle的render方法中也会检查FacesContext的responseComplete状态如果为true那么就不再执行render Phase于是我们此刻知道了在我们自己所写的一些代码或者JSF库里面的一些代码中调用FacesContext的responseComplete方法和renderResponse得作用原理render方法主要代码如下

if (!contextgetResponseComplete()) {

responsedoPhase(context thislistenerslistIterator());

}

另外注意Phase这个概念接口以及几个实现都是jsfri项目中的而在jsfapi中不存在Phase这个概念所以LifeCycle是JSF标准的内容而通过几个Phase来处理请求这种实现是sun的参考实现的做法

最后可以看到对于每一个phase都调用了doPhase方法同时把LifeCycle和FacesContext当做参数传入了值得注意的是所谓的phaseListener也传入了phase的doPhase方法中由此大约能够想明白这个阶段监听器的道理了

               

上一篇:用AJAX+J2EE实现一个网上会议室系统

下一篇:Jsp环境下的AJAX乱码问题