JSF應用中,在web.xml裡面配置了一個Servlet,叫做 javax.faces.webapp.FacesServlet,於是可以知道,查看、了解一個請求的處理過程可以從這裡開始。從官方網站上下載JSF 的源代碼,項目名比較古怪,叫做“mojarra”,我看的版本是1.2_12_b01。裡面包含了兩個子項目,一個是jsf-api,裡面大多是接口以及少量關鍵類。另外一個項目叫做jsf-ri,對著這個"ri"邪念了半天之後,終於在兄弟提醒之下想明白了是reference implementation的意思。jsf-api是JavaEE標准的一部分,裡面的類型包名都是以javax.faces開頭的,而jsf-ri項目是sun針對JSF標准的一個參考實現,裡面的類型的包名都是以com.sun.faces開頭的。
1.FacesServlet初始化(FacesServlet#init)
系統啟動的時候,會初始化FacesServlet,調用其中的init方法。裡面主要做了兩件事情,一個是初始化 FacesContextFactory,另外一個是初始化Lifecycle對象。在jsf-api項目中,FacesServlet類是一個 Servlet接口的實現類,而FacesContextFactory和Lifecycle都是接口。在jsf-ri項目中有這兩個接口的實現類,分別是com.sun.faces.context.FacesContextFactoryImpl和 com.sun.faces.lifecycle.LifecycleImpl類。一個想當然的事實:FacesServlet初始化的時候要根據一些配置來判斷具體的FacesContextFactory和Lifecycle實現類是什麼,也就是在這裡,“JSF標准”和“JSF實現”接軌了。想來 MyFaces等等的其他JSF實現應該不外乎兩種方式,一種是改變FacesServlet的init方法中需要用到的配置的值,於是啟用自己的 FacesContextFactory實現和Lifecycle實現,後面的處理過程就全部走自己的邏輯了。第二種方法笨一點,可能性不大,就是把 FacesServlet覆蓋替換掉,其中也不需要讀什麼配置了,直接使用自己的實現類即可——不過這種做法估計不符合JSF規范,想來只有我等蝦米民眾能做的出來。主要代碼如下:
1 facesContextFactory = (FacesContextFactory)FactoryFinder.getFactory(FactoryFinder.FACES_CONTEXT_FACTORY);
2
3 LifecycleFactory lifecycleFactory = (LifecycleFactory)FactoryFinder.getFactory(FactoryFinder.LIFECYCLE_FACTORY);
回頭再來看初始化的結果,FacesContextFactory很明顯是用來生產FacesContext這麼個東西的。而 FacesContext可以看做是一個RequestWrapper(注意這個FaceContext和ServletContext不一樣,ServletContext是一個Web應用只有一個的全局對象,對應的是一個Web application,而一個FacesContext對應的是一個request,另外,RequestWrapper這個說法不嚴格,實際上 FacesContext裡面也包裝了ServletContext、Response等)。而LifeCycle可以看做是一個過濾器鏈(類似於 servlet規范裡面的Filter Chain)。於是,整個JSF請求處理過程,實際上就是包裝成為FaceContext的用戶請求,通過類似於一個Filter Chain的LifeCycle的過程。