2011-04-04 57 views
24

這看起來不對。我正在做一些清理我的代碼,我只是注意到了這一點。每個Ajax請求都會觸發我的@ViewScoped bean的構造函數和@PostConstruct。即使是簡單的數據庫分頁也會觸發它。@ViewScoped在每個回發請求上調用@PostConstruct

I understood@ViewScoped長於@RequestScoped並且不應在每次請求時重新構建它。只有在通過GET重新加載完成頁面之後。

回答

43

換言之,您的@ViewScoped bean的行爲類似於@RequestScoped bean。它在每個回發請求中都從頭開始重新創建。造成這種情況的原因有很多,其中大部分原因歸結爲JSF狀態中不再提供關聯的JSF視圖,而JSF狀態又默認與HTTP會話相關聯。

假設您可以確保HTTP會話本身不是問題的根本原因,即當@SessionScoped絕對正常工作時,請查看以下可能原因列表。否則,如果HTTP會話本身也在每個請求上被丟棄並重新創建,那麼您需要退後一步,查看會話cookie和服務器配置。任何與HTTP會話斷開有關的原因至少超出了JSF的上下文。

  1. 您使用的鑽嘴魚科2.1.17或以上,且視圖包含了綁定視圖作用域Bean屬性,其期間view build time評估標籤屬性的EL表達式。例子是JSTL <c:if>,<c:forEach>等或者JSF <ui:include><x:someComponent id="#{...}",<x:someComponent binding="#{...}">等。這是由於Mojarra(issue 1492)中的一個錯誤引起的。另見Why does @PostConstruct callback fire every time even though bean is @ViewScoped? JSF

    這已經在Mojarra 2.1.18版中修復。如果您無法升級到新的版本中,解決方法是禁用部分狀態web.xml如下儲蓄,也看到JSTL in JSF2 Facelets... makes sense?

    <context-param> 
        <param-name>javax.faces.PARTIAL_STATE_SAVING</param-name> 
        <param-value>false</param-value> 
    </context-param> 
    

    或者當你要針對特定​​的一組唯一的JSF觀點:

    <context-param> 
        <param-name>javax.faces.FULL_STATE_SAVING_VIEW_IDS</param-name> 
        <param-value>/foo.xhtml;/bar.xhtml;/folder/baz.xhtml</param-value> 
    </context-param> 
    

    值得一提的是,將JSF組件的idbinding屬性的值綁定到視圖範圍的bean屬性是一種不好的做法。這些應該真的綁定到一個請求範圍的bean屬性,或者應該尋找替代方案。另請參閱How does the 'binding' attribute work in JSF? When and how should it be used?

  2. 您正在使用Mojarra 2.2.0,只有該版本在維護已在2.2.1中已修復的視圖範圍時存在(但未知)錯誤,另請參閱issue 2912。解決方案是升級到更新的版本。

  3. @ViewScoped註釋是從錯誤的包中導入的。 JSF提供了兩個@ViewScoped註釋,一個來自javax.faces.bean包,用於註釋爲@ManagedBean的JSF受管bean,另一個來自javax.faces.view包,用於註釋爲@Named的CDI受管bean。當bean範圍註釋與bean管理註釋不匹配時,實際的bean範圍將成爲bean管理框架的默認範圍,在JSF受管bean中爲@RequestScoped,在CDI受管bean中爲@Dependent

    你需要確保你有以下兩種結構的不混合使用它們,又見@ViewScoped bean recreated on every postback request when using JSF 2.2

    import javax.faces.bean.ManagedBean; 
    import javax.faces.bean.ViewScoped; 
    
    @ManagedBean 
    @ViewScoped 
    public class CorrectJSFViewScopedBean implements Serializable { 
    

    import javax.inject.Named; 
    import javax.faces.view.ViewScoped; 
    
    @Named 
    @ViewScoped 
    public class CorrectCDIViewScopedBean implements Serializable { 
    
  4. 的視圖是(意外?)經由<f:view transient="true">標記瞬態。這基本上打開了「無狀態的JSF」,這是自Mojarra 2.1.19以來的新增功能。因此,JSF視圖根本不會保存在JSF狀態中,而邏輯結果是所有引用的視圖範圍的bean都不能再與JSF視圖關聯。另請參見What is the usefulness of statelessness in JSF?

  5. Web應用程序配置了com.sun.faces.enableRestoreView11Compatibility方面的參數組到true不正確的企圖「避免」 ViewExpiredException。有了這個上下文參數,ViewExpiredException將永遠不會被拋出,但視圖(以及所有關聯的視圖範圍的bean)將從頭開始重新創建。但是,如果每次請求都發生這種情況,那麼這種方法實際上隱藏了另一個問題:視圖過期太快。這表示維護JSF視圖狀態和/或HTTP會話時可能存在問題。如何正確解決/配置,請前往javax.faces.application.ViewExpiredException: View could not be restored

  6. Web應用程序的運行時類路徑被污染有多個不同的版本化JSF API或IMPL相關的類。這會導致JSF視圖狀態的標識符/標記損壞/不匹配。您需要確保您的webapp的/WEB-INF/lib中沒有多個JSF API JAR文件。如果您使用的是Maven,請確保您將服務器提供的庫標記爲<scope>provided</scope>。另請參閱our JSF wiki page中的「安裝JSF」部分以及相關問題的答案:How to properly install and configure JSF libraries via Maven?

  7. 當你使用PrimeFaces <p:dialog>,那麼請確保<p:dialog>都有自己<h:form>,它沒有嵌套在另一個<h:form>。另見p:fileUpload inside p:dialog losing @ViewScoped values

  8. 當您將PrimeFaces FileUploadFilter與PrettyFaces結合使用時,請確保FileUploadFilter也在PrettyFaces重寫/轉發的請求上運行。另見ViewScoped bean rebuilt when FileUploadListener called using PrettyFacesHow to use PrimeFaces p:fileUpload? Listener method is never invoked or UploadedFile is null/throws an error/not usable

  9. 當您使用PrettyFaces時,將CSS/JS/image資源重定向到綁定到@ViewScoped bean的JSF頁面的配置錯誤的重寫規則也會導致誤導行爲。另見CDI ViewScope & PrettyFaces: Multiple calls to @PostConstruct (JSF 2.2)

+0

你是正確的。我在使用c:foreach的網頁上添加了一個函數。難怪我以前沒有注意到它。問題是用戶界面:重複不會在我的情況下工作。 http://primefaces.prime.com.tr/forum/viewtopic.php?f=3&t=59 將部分狀態保存工作與C:爲每個? – 2011-04-04 17:55:32

+0

不幸的是,禁用部分狀態保存並不能解決JSTL標籤的問題。然而這個特殊情況是棘手的。理論上你可以用一個完整的組件來解決這個問題,例如''它接受集合而不是''。我相信這是作爲對PrimeFaces的功能請求發佈的,不知道Cagatay對它做了什麼。 – BalusC 2011-04-04 18:07:33

+1

PARTIAL_STATE_SAVING改變了我的生活 – 2012-11-15 12:35:57