2013-01-09 25 views
7

我需要在另一個視圖範圍的bean中使用保存在視圖範圍的bean中的一些數據。在另一個視圖範圍的bean中注入一個視圖範圍的bean會導致它被重新創建

@ManagedBean 
@ViewScoped 
public class Attivita implements Serializable { 
    // 
} 

@ManagedBean 
@ViewScoped 
public class Nota implements Serializable { 

    @ManagedProperty("#{attivita}") 
    private Attivita attivita; 

    // Getter and setter. 
} 

現在,也許我的關於它的理論仍然是相當可憐的,我已經注意到,當#{attivita}被注入,該Attivita構造函數被調用,從而創造另一個實例。這是正確的行爲嗎?如果我想引用相同的實例而不創建新的實例,那麼呢?

+0

注意標記正確的答案。堆棧溢出不僅僅是關於答案的問題。 –

回答

13

這樣如果你從一個導航到另一個視圖上回發發生。視圖範圍的bean不綁定到請求,而是綁定到視圖。因此,當您導航到新視圖時,它將獲得視圖範圍bean的全新實例。它不會重用與先前視圖關聯的同一個bean實例。

據我所知,attivita bean是在初始視圖上創建的,並在回發時重用。我知道nota bean與您要導航到的新視圖關聯。當在其中注入attivita時,即使同一請求中有另一個實例,它也會簡單地獲得一個新的獨立實例。這是所有的預期(並承認有點不直觀)的行爲。

對此沒有標準的JSF解決方案。 CDI通過@ConversationScoped解決了這個問題(只要你明確地告訴它活着,bean就會生存)並且CDI擴展MyFaces CODI進一步跟@ViewAccessScoped(bean只要導航視圖引用它一直存在)進一步相關。

然而,您可以通過將bean作爲屬性存儲在請求範圍中來解決此問題。

@ManagedBean 
@ViewScoped 
public class Attivita implements Serializable { 

    public String submit() { 
     FacesContext.getCurrentInstance().getExternalContext() 
      .getRequestMap().put("attivita", this); 
     return "nota"; 
    } 

} 

@ManagedBean 
@ViewScoped 
public class Nota implements Serializable { 

    private Attivita attivita; 

    @PostConstruct 
    public void init() { 
     attivita = (Attivita) FacesContext.getCurrentInstance().getExternalContext() 
      .getRequestMap().get("attivita"); 
    } 

} 

請注意,這是相當哈克。取決於具體的功能要求,可能會有更好的解決方案。還請注意,您應該在nota視圖中將期望的Attivita bean實例指定爲#{nota.attivita}而不是作爲#{attivita},因爲由於前面已解釋的原因,它會爲您提供新的不同實例。

+0

這是肯定的 - 我有同樣的問題。然而,正如你所說的那樣,它非常黑客,並且還是JSF的另一大缺點。當你不得不添加一個PostConstruct並且必須手動從一個Faces上下文中取出一個bean時,它可以消除CDI或Managed Properties的作用。是否有計劃將@ViewAccessScoped添加到標準JSF API中,而不是僅作爲Myfaces的一部分? – GreenieMeanie

+0

@GreenieMeanie:JSF 2.2添加了@ @ FlowScoped來覆蓋這個,但不幸的是它仍然需要一些XML配置和自動生成的請求參數,因爲它還需要生存GET請求。就是說,'@ ViewAccessScoped'和'@ SessionScoped'之間。作爲一種可能的「更好的解決方案」,您可以考慮將實體ID重定向爲param,或者有條件地將另一個包含的視圖的部分視圖渲染出來。另見a.o. http://stackoverflow.com/questions/15521451/how-to-navigate-in-jsf-how-to-make-url-reflect-current-page-and-not-previous-o – BalusC

+0

你是否建議查看a.xhtml有一個包含b.xhtml的「虛擬」,並且可能將b.xhtml的所有內容封裝在一個巨大的ui中:當它被重定向到(通過b.xhtml)時,實際上只呈現任何東西的片段,而當它包含在a.xhtml中作爲虛擬參考? – GreenieMeanie

1

您的attivita bean是@ViewScoped並且不保證您的實例將被保留在會話中。你需要一個@SessionScoped bean。但是,如果由於某種原因需要attivita@ViewScoped,則可以通過其他方式將params傳遞給它們。使用viewParam或使用其他@SessionScoped bean。

頁PARAMS

http://mkblog.exadel.com/2010/07/learning-jsf2-page-params-and-page-actions/

JSF 2 Managed Bean的作用域

http://balusc.blogspot.com.es/2011/09/communication-in-jsf-20.html#ManagedBeanScopes

相關問題