生活随笔
收集整理的这篇文章主要介绍了
JSF 源代码赏析之FacesServlet
小编觉得挺不错的,现在分享给大家,帮大家做个参考.
学习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 { 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); } }
通过加载不同实现的LifecycleFactory对象,就可以允许加载不同的Lifecycle对象,这对于扩展JSF的功能是非常重要的,
当没有显示表明lifecycleId时,lifecycleFactory就会加载默认的lifecycleId,并根据lifecycleId加载Lifecycle对象
Lifecycle类负责JSF请求处理的全过程,主要是通过执行其中的execute方法和render方法实现的,FacesServlet的service方法很好的说明了这一点:
java 代码
public void service(ServletRequest request, ServletResponse response) throws IOException, ServletException { String pathInfo = ((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; } } FacesContext context = facesContextFactory.getFacesContext (servletConfig.getServletContext(), request, response, lifecycle); try { lifecycle.execute(context); lifecycle.render(context); } catch (FacesException e) { Throwable t = e.getCause(); if (t == null) { throw new ServletException(e.getMessage(), e); } else { if (t instanceof ServletException) { throw ((ServletException) t); } else if (t instanceof IOException) { throw ((IOException) t); } else { throw new ServletException(t.getMessage(), t); } } } finally { context.release(); } }
好了,FacesServlet的源码我们就看到这里,下一篇中我们将深入研究Lifecycle对象的执行过程,在最后,就让我们用myFaces的FacesServlet实现来结束吧:
myfaces之FacesServlet:
public final class FacesServlet implements Servlet { private static final Log log = LogFactory.getLog(FacesServlet.class); 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 String SERVLET_INFO = "FacesServlet of the MyFaces API implementation"; private ServletConfig _servletConfig; private FacesContextFactory _facesContextFactory; private Lifecycle _lifecycle; public FacesServlet() { super(); } public void destroy() { _servletConfig = null; _facesContextFactory = null; _lifecycle = null; if (log.isTraceEnabled()) log.trace("destroy"); } public ServletConfig getServletConfig() { return _servletConfig; } public String getServletInfo() { return SERVLET_INFO; } private String getLifecycleId() { String lifecycleId = _servletConfig.getServletContext() .getInitParameter(LIFECYCLE_ID_ATTR); return lifecycleId != null ? lifecycleId : LifecycleFactory.DEFAULT_LIFECYCLE; } public void init(ServletConfig servletConfig) throws ServletException { if (log.isTraceEnabled()) log.trace("init begin"); _servletConfig = servletConfig; _facesContextFactory = (FacesContextFactory) FactoryFinder .getFactory(FactoryFinder.FACES_CONTEXT_FACTORY); LifecycleFactory lifecycleFactory = (LifecycleFactory) FactoryFinder .getFactory(FactoryFinder.LIFECYCLE_FACTORY); _lifecycle = lifecycleFactory.getLifecycle(getLifecycleId()); if (log.isTraceEnabled()) log.trace("init end"); } public void service(ServletRequest request, ServletResponse response) throws IOException, ServletException { HttpServletRequest httpRequest = ((HttpServletRequest) request); String pathInfo = httpRequest.getPathInfo(); if (pathInfo != null && (pathInfo.startsWith("/WEB-INF") || pathInfo .startsWith("/META-INF"))) { StringBuffer buffer = new StringBuffer(); buffer.append(" Someone is trying to access a secure resource : " + pathInfo); buffer .append("/n remote address is " + httpRequest.getRemoteAddr()); buffer.append("/n remote host is " + httpRequest.getRemoteHost()); buffer.append("/n remote user is " + httpRequest.getRemoteUser()); buffer.append("/n request URI is " + httpRequest.getRequestURI()); log.warn(buffer.toString()); ((HttpServletResponse) response) .sendError(HttpServletResponse.SC_NOT_FOUND); return; } if (log.isTraceEnabled()) log.trace("service begin"); FacesContext facesContext = _facesContextFactory.getFacesContext( _servletConfig.getServletContext(), request, response, _lifecycle); try { _lifecycle.execute(facesContext); _lifecycle.render(facesContext); } catch (Throwable e) { if (e instanceof IOException) { throw (IOException) e; } else if (e instanceof ServletException) { throw (ServletException) e; } else if (e.getMessage() != null) { throw new ServletException(e.getMessage(), e); } else { throw new ServletException(e); } } finally { facesContext.release(); } if (log.isTraceEnabled()) log.trace("service end"); } }
总结
以上是生活随笔为你收集整理的JSF 源代码赏析之FacesServlet的全部内容,希望文章能够帮你解决所遇到的问题。
如果觉得生活随笔网站内容还不错,欢迎将生活随笔推荐给好友。