学习JSF 多日,现在开始看看源代码。
首先是FacesServlet类了,作为一个前端控制器,每一个JSF请求都要通过FacesServlet,然后再到其他阶段,那么,FacesServlet 到底做了些什么操作呢?
文件头部的注释
头部注释说的很明白,管理请求的处理周期。至于怎么管理,下面先来看一看到底声明了什么变量
变量
-
- public static final String CONFIG_FILES_ATTR =
- "javax.faces.CONFIG_FILES";
-
- public static final String LIFECYCLE_ID_ATTR =
- "javax.faces.LIFECYCLE_ID";
-
- private static final Logger LOGGER =
- Logger.getLogger("javax.faces.webapp", "javax.faces.LogStrings");
- private FacesContextFactory facesContextFactory = null;
- private Lifecycle lifecycle = null;
- private ServletConfig servletConfig = null;
上面这些变量都是FacesServlet的全局变量,也就是整个JSF 应用的全局变量,其中最主要的我都加粗了,可以看出,主要涉及到FacesContextFactory、LifeCycle和ServletConfig对象,其中的ServletConfig对象不难理解,基于Servlet技术的表现层框架都需要这个类,而FacesContextFactory和LifeCycle则有些研究了。
FacesContextFactory是一个实现了工厂模式的抽象类,用来创建(如果没有的话)和返回一个FacesContext实例,并且把这个实例初始化,以便处理request和response对象。至于这个FacesContext对象,则是始终贯彻在JSF中的一个对象,下面自然会慢慢讲解,现在需要知道的是,FacesContext也是一个抽象类就可以。
现在先看一下FacesContextFactory对象和FacesContext的关系。顾名思义,工厂模式,就是专门生产产品的,FacesContextFactory工厂则是专门产生FacesContext对象的,FacesContextFactory对象提供了下面的方法:
FacesContextFactory
- public abstract FacesContext getFacesContext
- (Object context, Object request,
- Object response, Lifecycle lifecycle)
- throws FacesException;
来产生FacesContext对象,并且这是一个抽象方法,如何调用,则是JSF实现的事情了,并且FacesContextFactory会为每一个Request请求返回一个FacesContext对象。注意,这里用的是“返回”,而不是生成,是因为FacesContextFactory并不一定会为每一个请求生成一个新的FacesContext对象,FacesContext对象有一个release方法,这个方法负责释放FacesContext的资源,在调用这个方法之前,通过FacesContext.getCurrentInstance可以返回当前线程上的实例,这样实现FacesContext在某种程度上的重用和pool。
下面应该来看看在FacesServlet中如何调用FacesContextFactory来产生一个FacesContext对象了。
首先要产生一个FacesContextFactory对象,这是通过FacesServlet的init方法来实现的:
FacesServlet的init方法
- public void init(ServletConfig servletConfig) throws ServletException {
-
-
- this.servletConfig = servletConfig;
-
-
- try {
- facesContextFactory = (FacesContextFactory)
- FactoryFinder.getFactory
- (FactoryFinder.FACES_CONTEXT_FACTORY);
- } catch (FacesException e) {
- ResourceBundle rb = LOGGER.getResourceBundle();
- String msg = rb.getString("severe.webapp.facesservlet.init_failed");
- Throwable rootCause = (e.getCause() != null) ? e.getCause() : e;
- LOGGER.log(Level.SEVERE, msg, rootCause);
- throw new UnavailableException(msg);
- }
-
-
- try {
- LifecycleFactory lifecycleFactory = (LifecycleFactory)
- FactoryFinder.getFactory(FactoryFinder.LIFECYCLE_FACTORY);
- String lifecycleId ;
-
-
- if (null == (lifecycleId = servletConfig.getInitParameter(LIFECYCLE_ID_ATTR))) {
- lifecycleId = servletConfig.getServletContext().getInitParameter
- (LIFECYCLE_ID_ATTR);
- }
-
- if (lifecycleId == null) {
- lifecycleId = LifecycleFactory.DEFAULT_LIFECYCLE;
- }
- lifecycle = lifecycleFactory.getLifecycle(lifecycleId);
- } catch (FacesException e) {
- Throwable rootCause = e.getCause();
- if (rootCause == null) {
- throw e;
- } else {
- throw new ServletException(e.getMessage(), rootCause);
- }
- }
-
- }
在这个init方法中,FacesServlet通过FactoryFinder对象来创建一个具体的Factory对象,这样就把创建Factory对象的工作给托管给其他的类了,同时这个FactoryFinder还可以创建其他的工厂类,因此可以说FactoryFinder是“工厂的工厂”,是专门创造工厂的类。通过
FactoryFinder.FACES_CONTEXT_FACTORY参数指明是创建FacesContextFactory,FactoryFinder就给创建出一个FacesContextFactory。
下面我们就来看看FactoryFinder是通过什么算法,来查找和创建JSF实现中的各个工厂类。
FactoryFinder通过实现标准的发现算法,可以查找所有在JSF API中指定的factory对象,这个算法是这样的:
1.如果web应用的WEB-INF目录下存在JSF的configuration 文件,并且含有factory节点,而且这个factory节点中含有正在查找的factory对象的类名称,那么就加载这个类。
2.如果在ServletContext的初始化参数中有javax.faces.CONFIG_FILES
参数,并且这个参数值指定的配置文件中有factory节点,并且这个节点中含有目前正在查找的factory类名,那么就加载这个对象。
3.如果在ServletContext的资源目录下的Jar包中的 META-INF目录下含有JSF配置文件,并且正在查找的factory类名存在于factory节点中,则加载这个类。最晚加载的类优先。
4.如果META-INF/service/目录下有当前正在查找的类名称,会加载之。
5.如果上面的规则都没有匹配,则会使用JSF实现中的特定类。
这种算法的缺点就是每一个Web应用都会有一个自己的factory实例,不管这个JSF实现是包含在Web应用chengx程序之中还是在容器中作为一个共享库存在。
这个FactoryFinder还是蛮复杂的,以后有时间将另外撰文研究。
下面的事情就是LifecycleFactory的加载了,其加载过程不必多言。
LifecycleFactory对象加载后,会查找JSF中是否配置了javax.faces.LIFECYCLE_ID参数,根据这个参数加载lifecycleId,整个过程是这样的:
加载LifecycleFactory
-
-
try{
-
LifecycleFactorylifecycleFactory=(LifecycleFactory)
-
FactoryFinder.getFactory(FactoryFinder.LIFECYCLE_FACTORY);
-
StringlifecycleId;
-
-
-
if(null==(lifecycleId=servletConfig.getInitParameter(LIFECYCLE_ID_ATTR))){
-
-
lifecycleId=servletConfig.getServletContext().getInitParameter
-
(LIFECYCLE_ID_ATTR);
-
}
-
-
if(lifecycleId==null){
-
lifecycleId=LifecycleFactory.DEFAULT_LIFECYCLE;
-
}
-
lifecycle=lifecycleFactory.getLifecycle(lifecycleId);
-
}catch(FacesExceptione){
-
ThrowablerootCause=e.getCause();
-
if(rootCause==null){
-
throwe;
-
}else{
-
thrownewServletException(e.getMessage(),rootCause);
-
}
-
}
通过加载不同实现的LifecycleFactory对象,就可以允许加载不同的Lifecycle对象,这对于扩展JSF的功能是非常重要的,
当没有显示表明lifecycleId时,lifecycleFactory就会加载默认的lifecycleId,并根据lifecycleId加载Lifecycle对象
Lifecycle类负责JSF请求处理的全过程,主要是通过执行其中的execute方法和render方法实现的,FacesServlet的service方法很好的说明了这一点:
java 代码
-
publicvoidservice(ServletRequestrequest,
-
ServletResponseresponse)
-
throwsIOException,ServletException{
-
-
-
-
StringpathInfo=((HttpServletRequest)request).getPathInfo();
-
if(pathInfo!=null){
-
pathInfo=pathInfo.toUpperCase();
-
if(pathInfo.startsWith("/WEB-INF/")
-
||pathInfo.equals("/WEB-INF")
-
||pathInfo.startsWith("/META-INF/")
-
||pathInfo.equals("/META-INF")){
-
((HttpServletResponse)response).
-
sendError(HttpServletResponse.SC_NOT_FOUND);
-
return;
-
}
-
}
-
-
-
FacesContextcontext=facesContextFactory.getFacesContext
-
(servletConfig.getServletContext(),request,response,lifecycle);
-
-
-
try{
-
lifecycle.execute(context);
-
lifecycle.render(context);
-
}catch(FacesExceptione){
-
Throwablet=e.getCause();
-
if(t==null){
-
thrownewServletException(e.getMessage(),e);
-
}else{
-
if(tinstanceofServletException){
-
throw((ServletException)t);
-
}elseif(tinstanceofIOException){
-
throw((IOException)t);
-
}else{
-
thrownewServletException(t.getMessage(),t);
-
}
-
}
-
}
-
finally{
-
-
context.release();
-
}
-
-
}
好了,FacesServlet的源码我们就看到这里,下一篇中我们将深入研究Lifecycle对象的执行过程,在最后,就让我们用myFaces的FacesServlet实现来结束吧:
myfaces之FacesServlet:
分享到:
相关推荐
JavaEE源代码 jsf-apiJavaEE源代码 jsf-apiJavaEE源代码 jsf-apiJavaEE源代码 jsf-apiJavaEE源代码 jsf-apiJavaEE源代码 jsf-apiJavaEE源代码 jsf-apiJavaEE源代码 jsf-apiJavaEE源代码 jsf-apiJavaEE源代码 jsf-...
JavaEE源代码 jsf-implJavaEE源代码 jsf-implJavaEE源代码 jsf-implJavaEE源代码 jsf-implJavaEE源代码 jsf-implJavaEE源代码 jsf-implJavaEE源代码 jsf-implJavaEE源代码 jsf-implJavaEE源代码 jsf-implJavaEE源...
sun 最新框架,jsf写的j2ee项目代码
jsf 新生的 web 开发框架
JSF2.0源代码,具体版本是2.03。但与其它版本差别不太,适用下不了源码的GGMM。
自己写的JSF文件上传项目,可以最大支持最大1.99G文件 需要的jar包需奥自己加 附:jar目录截图
JSF工程实例源代码,包含实现文件上传与下载的全部源代码和文档,数据库使用oracle10g
jsf1.2源代码。可用myeclipse关联起来查看里边源码。
jsf教程实例的源代码,有利于读者更好的学习。
Core JSF(JSF核心技术)就不用我介绍了吧,这是该书的源码
richface,jsf源码。相当不错的资料。特别是richface.里面有不错的例子。放到tomcat下可以直接运行啊。
jsf-1_2_07-src
JSF国际化范例,源代码 JSF国际化范例,源代码 JSF国际化范例,源代码
JSF的源代码,即是jsf本身框架的源代码,通过阅读可以更好地学习JSF,深入理解它的精髓。
一个小例子适合jsf入门者。本人自己敲的代码 完全可用 启动服务器(tomcat)部署之后 输入:http://localhost:8080/HelloJsf/HelloWorld.faces就可以了
JSF IN ACTION (源代码) 以前上传的书的源代码.......IN Action书的代码都可以在Manning 的官方网站(www.manning.com)上可以下载得到..希望大家喜欢
jsf in Action源代码(6-10章) jsf实战源代码(6-10章) javaserver Faces in Actionjsf 源代码(6-10章)
jsf完全参考手册源代码