生活随笔
收集整理的這篇文章主要介紹了
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的全部內容,希望文章能夠幫你解決所遇到的問題。
如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。