一、前言
在創建JSF的FacesContext的對象時,像之前絕大多數做法一樣。
- 首先,在class的公共域聲明並創建facesContext對象(未初始化);
FacesContext facesContext = FacesContext.getCurrentInstance();
然後,在方法中實例化上面創建的facesContext對象並調用該對象;
聲明:JSF的FacesContext對象的實例化方式比較特別,它是在發起JSF請求時初始化facesContext對象的(正是因爲這個原因導致報錯,這一點在下一節裏講解)。
facesContext.addMessage(null,new FacesMessage("Hello!");
然而,部署完後報錯:
17:27:10,839 ERROR [io.undertow.request] (default task-41) UT005023: Exception handling request to /labmanagement/home.jsf: javax.servlet.ServletException: javax.servlet.ServletException: java.lang.IllegalStateException
二、FacesContext簡介
FacesContext是faces中經常用到的兩個接口,對於每一個JSF請求,FacesServlet都會生成一個對應的FacesContext,然後在創建的Context中進行相關的操作。所以FacesContext對象只能在一個JSF請求的週期中產生,實際上它是調用靜態的getCurrentInstance方法,返回當前的FacesContext實例。在”前言”部分調用該靜態getCurrentInstance方法的作用域沒有JSF請求,這也就導致了上文中出現IllegalStateException。
對於FacesContext的理解可以結合JPA中的persistence context進行理解。
三、FacesContext對象實例化
3.1 實例化方法一
參照”前言”部分,將
FacesContext facesContext = FacesContext.getCurrentInstance();
該方法的調用放在JSF的請求處理週期中,FacesServlet才能獲取到FacesContext實例。
3.2 實例化方法二
使用CDI的依賴注入,向容器事先申請一個FacesContext(組件注入FacesContext對象facesContext),
@Inject
FacesContext facesContext;
然後在實際調用該FacesContext對象時調用即可。
facesContext.addMessage(null,new FacesMessage("Hello!");
四、CDI注入理解
4.1 方法一分析
上文中的方法一,
FacesContext facesContext = FacesContext.getCurrentInstance();
由於沒有處於JSF的請求週期中,所以靜態的getCurrentInstance方法無法獲取該FacesContext實例,即該對象實際上是沒有實例化的,所以後面也就沒法調用了。
4.2 方法二分析
使用CDI的依賴注入,向容器事先申請一個FacesContext組件,此時並沒有實例化。但是在後文調用這個組件時就能得到及時實例化。
(其實我也不理解)
五、完整代碼
@Inject
StuffFacade stuffService;
facesContext.addMessage(null,new FacesMessage("Hello!");