2013-04-24 12 views
5

Tôi chỉ cần trang được liên kết @RequestScoped bean sao lưu. Tôi truy cập trang này từ trang khác mà trên đó tôi đã chuyển thông số "project". Vì vậy, khi tôi nhận được trên trang bên phải tôi có url như contextRoot/faces/jsf.xhtml?project=123.Giữ lại các tham số yêu cầu GET ban đầu trên postbacks

Xem:

<f:metadata> 
    <f:viewParam name="project" value="#{entityBean.projectId}" /> 
</f:metadata>  
... 
<p:commandButton value="#{msg['button.add']}" 
    actionListener="#{entityBean.addNewEntity((entityName),(entityDescritpion))}" 
    ajax="true" update=":projectDetailForm"/> 

Sao đậu:

@Named("entityBean") 
@RequestScoped 
public class EntityBean implements Serializable{ 
    private String projectId; 

    @PostConstruct 
    public void init() { 
     params = FacesContext.getCurrentInstance().getExternalContext().getRequestParameterMap(); 

     for (Map.Entry<String, String> entry : params.entrySet()) { 
      System.out.println(entry.getKey() + "/" + entry.getValue()); 
     } 

     if (params.get("project") != null) { 
      projectId = params.get("project"); 
     } else { 
      HttpServletRequest request = 
       (HttpServletRequest)FacesContext.getCurrentInstance().getExternalContext().getRequest(); 
      String projectId = request.getParameter("project"); 
     } 
    } 

    //projectId getter and setter 
    //public void addNewEntity(String name, String desc) {} 
} 

Tất cả mọi thứ hoạt động tốt khi trang được mở ra lần đầu tiên. Tham số GET được xử lý thành công. Tuy nhiên, khi bean được yêu cầu phạm vi, nó bị hủy bởi kết thúc yêu cầu và được tạo lại trên (các) postback tiếp theo. Trong các postback này, tham số GET không còn khả dụng nữa mặc dù nó có thể nhìn thấy trong thanh địa chỉ trình duyệt. Tôi đã thử ba phương pháp lấy thông số bởi f:viewParamExternalContext và thậm chí từ ServletContext nhưng tôi không thể nhận được các thông số đó.

Tôi không muốn thay đổi @RequestScoped thành @SessionsScoped và tôi không thể sử dụng @ViewScoped, vì tôi đang sử dụng hạt CDI và tôi không muốn kết hợp chúng.

+0

thay đổi Phạm vi Bean từ "yêu cầu" thành "Chế độ xem". – KSHiTiJ

+1

@kshitij: thật không may, OP đang sử dụng CDI thay vì JSF để quản lý đậu. Vì vậy, phạm vi xem cụ thể JSF sẽ không hoạt động. OP cũng đã đề cập rõ ràng nó trong câu cuối cùng của câu hỏi. – BalusC

Trả lời

9

Bạn cần <f:param> trong thành phần UICommand để giữ lại các thông số yêu cầu cho yêu cầu tiếp theo. Ví dụ.

<p:commandButton ...> 
    <f:param name="project" value="#{param.project}" /> 
</p:commandButton> 

Ngoài ra, bạn có thể sử dụng <o:form> của tiện ích thư viện JSF OmniFaces, nó về cơ bản mở rộng <h:form> với một thuộc tính thêm includeViewParams cho phép bạn giữ lại các thông số yêu cầu đăng ký qua <f:viewParam> cho yêu cầu tiếp theo.

<o:form includeViewParams="true"> 
    ... 
</o:form> 

Điều này có thể dễ dàng hơn nếu bạn có nhiều nút/liên kết lệnh và hành động ajax.

URL trong thanh địa chỉ trình duyệt trong trường hợp của bạn không thay đổi vì bạn đang kích hoạt yêu cầu ajax. Nhưng URL thực tế, mà bạn có thể thấy trong <form action> của đầu ra HTML được tạo thông qua click chuột phải - Xem nguồn trong trình duyệt, theo mặc định không chứa các tham số GET hiện tại.


Không liên quan cho vấn đề cụ thể, với tay lấy các tham số trong postconstruct, bạn đang bỏ qua cơ bản tính hữu ích và quyền hạn của <f:viewParam>. Tôi khuyên bạn nên cẩn thận đi qua các câu trả lời sau đây để học cách sử dụng chúng đúng cách:

+0

Để giải quyết vấn đề này, tôi đã sử dụng Apache MyFaces CODI. Nó cung cấp các phần mở rộng rất hữu ích cho các phạm vi CDI như ViewAccessScoped. Wokrs tốt với JSF 2.0 và Primefaces. – AdrianX

+0

@AdrianX: Cũng có thể. Nó chỉ để lại các tham số 'windowId' xấu trong URL. Lưu ý rằng nó cũng cần JSF '@ ViewScoped' trong suốt tới CDI để bạn có thể sử dụng' @Named @ ViewScoped'. – BalusC