2012-06-25 36 views
27

Từ những gì tôi hiểu, các đối tượng được đặt bên trong phạm vi Flash trong vòng đời yêu cầu khuôn mặt sẽ có sẵn cho vòng đời yêu cầu khuôn mặt tiếp theo và sau đó xóa.Hiểu phạm vi flash trong JSF2

Giả sử tôi có hai trang:

page01.xhtml:

<h:form> 
    <h:commandButton action="#{page01Bean.action}" /> 
</h:form> 

Page01Bean:

@ManagedBean 
@RequestScoped 
public class Page01Bean { 

     public void action(){ 
      FacesContext.getCurrentInstance().getExternalContext().getFlash().put("fooKey", "fooValue"); 
     } 

} 

page02.xhtml:

<h:outputText value="#{flash.fooKey}"/> 

Vì vậy, khi các nút trong page01.xhtml được nhấp, một khuôn mặt yêu cầu vòng đời (nói vòng đời A) bắt đầu và thiết lập giá trị để flash dưới phím gọi fooKey

Sau đó, tôi mở tab trình duyệt khác và duyệt page02.xhtml. Một khuôn mặt yêu cầu vòng đời (nói vòng đời B) bắt đầu để render trang này. Tôi hy vọng rằng vòng đời B có thể truy cập phạm vi đèn flash của vòng đời trước đó (tức là vòng đời A) và hiển thị fooValue trong page02.xhtml. Tuy nhiên, nó không hiển thị gì cả.

Vui lòng sửa tôi những gì tôi hiểu sai về phạm vi flash trong ví dụ này. Cảm ơn rất nhiều

Trả lời

30

Tóm lại, các biến được lưu trữ trong phạm vi flash sẽ tồn tại được chuyển hướng và chúng sẽ bị loại bỏ sau đó. Điều này thực sự hữu ích khi triển khai mẫu Post-Redirect-Get.

Nếu bạn cố điều hướng đến trang khác bằng cách chuyển hướng và truy cập thuộc tính khi tải, chúng sẽ ở đó. Sau khi yêu cầu đó được thực hiện, các giá trị trong flash sẽ bị loại bỏ. Ví dụ:

Bạn đang ở trang1.xhtml và bạn có lệnh liên kết chuyển hướng đến một trang mới với phương thức như thế này (Lưu ý: Tôi sẽ sử dụng điều hướng ngầm).

public String navigateToPageB() { 
    FacesContext.getCurrentInstance().getExternalContext().getFlash().put("param1", "Hello World!"); 
    return "pageB?faces-redirect=true"; 
} 

Khi pageB.xhtml được trả lại, bạn có thể truy cập vào những giá trị của biểu thức EL như

<h:outputLabel value="#{flash['param1']}" /> 

đó sẽ hiển thị "Hello World!" chuỗi chúng tôi đã lưu trước đó trong navigationToPageB.

Đối với câu hỏi của bạn, bằng cách mở tab mới trong trình khám phá, bạn không truy cập cùng ngữ cảnh mà bạn đang truy cập trên tab trước, do đó biến của bạn sẽ không khả dụng ở đó.

23

Câu trả lời trước là chính xác, nhưng chỉ để hoàn thành, tôi muốn nói rằng đã có một lot of issues trong triển khai Mojarra với tất cả những thứ này, nhưng cuối cùng họ đã đạt được để làm cho nó hoạt động đúng trong Mojarra 2.1.27 và 2.2.5 phiên bản .

Như @Gamb cho biết, mục đích của phạm vi flash là giữ cho tham số tiếp tục ánh xạ nó trong nội bộ qua chuyển hướng. Chúng ta cũng có thể giữ cho tham số tồn tại lâu hơn nếu chúng ta cần nó. Ngoài cách được đề cập, FacesContext#getCurrentInstance#getExternalContext#getFlash#put, cũng có cơ hội để đặt tham số thông qua biểu thức EL, sử dụng <c:set />.Tôi đã thực hiện một thử nghiệm cơ bản sau SSCCE trong đó cho thấy một phạm vi rộng các lựa chọn, sử dụng hai quan điểm:

Bean1

@ManagedBean 
@ViewScoped 
public class Bean1 implements Serializable { 

    /** 
    * Just takes the given param, sets it into flash context and redirects to 
    * page2 
    * 
    * @param inputValue 
    * @return 
    */ 
    public String goPage2(String inputValue) { 
     FacesContext.getCurrentInstance().getExternalContext().getFlash() 
       .put("param", inputValue); 
     return "page2?faces-redirect=true"; 
    } 

} 

page1.xhtml

<html xmlns="http://www.w3.org/1999/xhtml" 
    xmlns:h="http://java.sun.com/jsf/html" 
    xmlns:ui="http://java.sun.com/jsf/facelets" 
    xmlns:c="http://java.sun.com/jsp/jstl/core"> 
<h:head /> 
<h:body> 

    <!-- Sets the first flash param at the action method, which redirects to page 2 --> 
    <h:form> 
     <h:inputText value="#{inputValue}" /> 
     <h:commandButton action="#{bean1.goPage2(inputValue)}" 
      value="Go Page 2" /> 
    </h:form> 

    <!-- Sets the second flash param --> 
    <c:set target="#{flash}" property="param2" value="Myparam2" /> 

    <!-- Tries to retrieve both of the params. 
    Note none of them is displayed at the first page hit. 
    If page refreshed, the second param which has been already set 
    using c:set above, will be displayed --> 
    <p>Param1: #{flash['param']}</p> 
    <p>Param2: #{flash['param2']}</p> 
</h:body> 
</html> 

Bean2

@ManagedBean 
@ViewScoped 
public class Bean2 implements Serializable { 

    public String getParam() { 
     /** 
     * Takes the parameter from the flash context 
     */ 
     return (String) FacesContext.getCurrentInstance().getExternalContext() 
       .getFlash().get("param"); 
    } 

} 

page2.xhtml

<html xmlns="http://www.w3.org/1999/xhtml" 
    xmlns:h="http://java.sun.com/jsf/html" 
    xmlns:ui="http://java.sun.com/jsf/facelets" 
    xmlns:f="http://java.sun.com/jsf/core"> 
<h:head /> 
<!-- This page just displays the received params --> 
<h:body> 
    <!-- Different ways to retrieve the params from the flash scope --> 
    <p>Param1: #{bean2.param}</p> 
    <p>Param1: #{flash.param}</p> 
    <p>Param1: #{flash['param']}</p> 
    <p>Param2: #{flash['param2']}</p> 

    <!-- Keep the first param for next redirection --> 
    #{flash.keep.param} 

    <!-- Return to page1 and see how the first param is retained --> 
    <h:button outcome="page1?faces-redirect=true" value="return to 1" /> 
</h:body> 
</html> 

Xem thêm:

+1

+1 đề cập đến việc thực hiện buggy, nó bối rối địa ngục ra khỏi tôi. – mabi

+0

Đặt nó qua EL đã không làm các trick cho tôi, nhưng thay vào đó, tôi có thể đề nghị để đặt nó vào một bean được quản lý: 'FacesContext.getCurrentInstance(). GetExternalContext(). GetFlash(). Keep (" oValue "); \t \t this.oValue = (ValueClass) FacesContext.getCurrentInstance(). GetExternalContext(). GetFlash(). Get ("oValue"); ' Nó hoạt động để' TẢI lại trang một lần nữa, nhưng nó sẽ phá vỡ bằng cách nào đó sau ajax request + 'GET'. – DanielK