我們在啓用了JSF 2.2 + PrimeFaces的應用程序中使用SPA方法。 最初描述的基本想法非常好位置:使用@ViewScoped Bean時刪除SPA JSF 2.2應用程序中的@ViewScoped bean
Refreshing dynamic content with AJAX in JSF using SPA approach
但是,我們知道,使用這種方法SPA有一個缺點。
由於我們實際上總是停留在相同的JSF視圖中,因此當我們用新的SPA內容替換面板組的內容時,不會從內存中刪除@ViewScoped bean。
我找到了一個解決方案,但我想知道它是否是正確的方法,和/或是否有任何缺失。
基本上,我們的NavigationService豆,持有該頁面的名稱SPA AJAX請求期間被渲染,我們始終執行下面的代碼:
private void clearViewScopedBeans() {
Map<String, Object> viewMap = FacesContext.getCurrentInstance().getViewRoot().getViewMap();
for(Iterator<Map.Entry<String, Object>> it = viewMap.entrySet().iterator(); it.hasNext();) {
Map.Entry<String, Object> entry = it.next();
it.remove();
}
}
這應該確保,新的SPA之後代碼片段被渲染,所有以前存在的@ViewScoped bean都被刪除。
但是,我認爲上面的代碼只會刪除查看範圍的bean,而不是相關的視圖狀態。那是對的嗎 ?
,我發現一箇舊博客條目,這似乎做多一點的邏輯: http://javaevangelist.blogspot.sg/2014/08/jsf-21-tip-of-day-clearing-viewscope.html
,但我不知道它是否是正確的爲好。
此外,如果我們要支持多個窗口標籤,我們的NavigationService豆,保存當前SPA片斷頁面名稱,必須@ViewScoped爲好,這引入了一個小問題:
當運行上面的代碼用於刪除所有現有的@ViewScoped bean ...我們必須排除NavigationService bean本身!否則,我們會始終加載相同的頁面,因爲NavigationService的新實例會實例化,並且會使用默認的SPA頁面名稱,而不是新的實例。因此,總而言之,我們的代碼看起來終於如此,我們在其中保留一個「排除的」bean名稱的Map,我們不想在SPA頁面上刷新(即保存SPA的NavigationService bean頁面名稱)
private void clearViewScopedBeans() {
Map<String, Object> viewMap = FacesContext.getCurrentInstance().getViewRoot().getViewMap();
for(Iterator<Map.Entry<String, Object>> it = viewMap.entrySet().iterator(); it.hasNext();) {
Map.Entry<String, Object> entry = it.next();
if(!exclusionViewScopedBeans.contains(entry.getKey())) {
logger.info("Removing an instance of a @ViewScoped bean -> " + entry.getKey());
it.remove();
}
}
}
現在的問題...... 這是正確的做法處理這些類型的SPA情況呢?我們在這裏錯過了什麼嗎?
任何反饋將不勝感激...先謝謝了很多!
那就是我使用的實現 - 就正確的方法而言,我得到的印象是您應該避免使用JSF中的這種類型,但實際情況有時需要 – farrellmr
爲什麼不使用對話作用域bean? – Kukeltje
因爲這個特定的項目使用Spring IoC而不是CDI,所以目前沒有內置的對話範圍。 (在任何情況下,我也在研究創建可以實現相同功能的新(Spring)範圍。到目前爲止,我已成功爲PrimeFaces TabView組件創建了一個TabScope,每個Tab都可以有自己的JSF bean範圍,當標籤被構建時創建,當標籤關閉時被銷燬,我想我可以使用相同的方法來開發更通用的對話範圍... –