日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 前端技术 > javascript >内容正文

javascript

JSF 源代码赏析之FacesServlet

發布時間:2025/3/16 javascript 31 豆豆
生活随笔 收集整理的這篇文章主要介紹了 JSF 源代码赏析之FacesServlet 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

學習JSF 多日,現在開始看看源代碼。
首先是FacesServlet類了,作為一個前端控制器,每一個JSF請求都要通過FacesServlet,然后再到其他階段,那么,FacesServlet 到底做了些什么操作呢?

文件頭部的注釋
  • /**
  • *

    FacesServlet is a servlet that manages the request

  • * processing lifecycle for web applications that are utilizing JavaServer
  • * Faces to construct the user interface.

    ?

  • */
  • 頭部注釋說的很明白,管理請求的處理周期。至于怎么管理,下面先來看一看到底聲明了什么變量
    變量
  • 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 {
  • // Save our ServletConfig instance
  • this.servletConfig = servletConfig;
  • // Acquire our FacesContextFactory instance
  • 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);
  • }
  • // Acquire our Lifecycle instance
  • try {
  • LifecycleFactory lifecycleFactory = (LifecycleFactory)
  • FactoryFinder.getFactory(FactoryFinder.LIFECYCLE_FACTORY);
  • String lifecycleId ;
  • // First look in the servlet init-param set
  • if (null == (lifecycleId = servletConfig.getInitParameter(LIFECYCLE_ID_ATTR))) {
  • // If not found, look in the context-param set
  • 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
  • //?Acquire?our?Lifecycle?instance??
  • ???????try?{??
  • ???????????LifecycleFactory?lifecycleFactory?=?(LifecycleFactory)??
  • ???????????????FactoryFinder.getFactory(FactoryFinder.LIFECYCLE_FACTORY);??
  • ???????????String?lifecycleId?;??
  • ??
  • ???????????//?First?look?in?the?servlet?init-param?set??
  • ???????????if?(null?==?(lifecycleId?=?servletConfig.getInitParameter(LIFECYCLE_ID_ATTR)))?{??
  • ???????????????//?If?not?found,?look?in?the?context-param?set???
  • ???????????????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?{ ??
  • ??
  • ???????//?If?prefix?mapped,?then?ensure?requests?for?/WEB-INF?are ??
  • ???????//?not?processed. ??
  • ???????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; ??
  • ???????????} ??
  • ???????}???? ??
  • ??????? ??
  • ???????//?Acquire?the?FacesContext?instance?for?this?request ??
  • ???????FacesContext?context?=?facesContextFactory.getFacesContext ??
  • ???????????(servletConfig.getServletContext(),?request,?response,?lifecycle); ??
  • ??
  • ???????//?Execute?the?request?processing?lifecycle?for?this?request ??
  • ???????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?{ ??
  • ???????????//?Release?the?FacesContext?instance?for?this?request ??
  • ???????????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); ??
  • ????????//?TODO:?null-check?for?Weblogic,?that?tries?to?initialize?Servlet ??
  • ????????//?before?ContextListener ??
  • ??
  • ????????//?Javadoc?says:?Lifecycle?instance?is?shared?across?multiple ??
  • ????????//?simultaneous?requests,?it?must?be?implemented?in?a?thread-safe ??
  • ????????//?manner. ??
  • ????????//?So?we?can?acquire?it?here?once: ??
  • ????????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?it?is?a?prefix?mapping?... ??
  • ????????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()); ??
  • ??
  • ????????????//?Why?does?RI?return?a?404?and?not?a?403,?SC_FORBIDDEN?? ??
  • ??
  • ????????????((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的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。