2012-04-27 62 views
11

後,我有一個需要用戶ID的工作了幾頁,因此下面的代碼:處理視圖參數JSF後

userpage.xhtml

<!-- xmlns etc. omitted --> 
<html> 
<f:metadata> 
    <f:viewParam name="userId" value="#{userPageController.userId}"/> 
</f:metadata> 
<f:view contentType="text/html"> 
<h:head> 
</h:head> 
<h:body> 
    <h:form> 
     <h:commandButton action="#{userPageController.doAction}" value="post"/> 
    </h:form> 
</h:body> 
</f:view> 

userPageController.java

@Named 
@ViewScoped 
public class userPageControllerimplements Serializable { 
    private static final long serialVersionUID = 1L; 

    @Inject protected SessionController sessionController; 
    @Inject private SecurityContext securityContext; 
    @Inject protected UserDAO userDAO; 

    protected User user; 
    protected Long userId; 

    public UserPage() { 
    } 

    public User getUser() { 
     return user; 
    } 

    public void setUser(User user) { 
     this.user = user; 
    } 

    public Long getUserId() { 
     return userId; 
    } 

    public void setUserId(Long userId) { 
     if(!FacesContext.getCurrentInstance().isPostback()){ 
      User u = userDAO.find(userId); 
      this.userId = userId; 
      this.user = u; 
     } 
    } 

    public void doAction(){ 

    } 

} 

但是,在調用doAction之後,url中的視圖參數消失。由於它的視圖性質,該bean仍然有效,但它破壞了我對未來導航的嘗試。當我搜索周圍時,我得到一個印象,即在閱讀userpage.jsf?userId = 123後,視圖參數應該保留,但事實並非如此。什麼是真正的預期行爲?

與此相關,我試圖在導航到另一個頁面時自動添加視圖參數,我希望保留userId。它似乎適用於其他人,但對我而言,ViewRoot中的userId始終爲空。下面的代碼用於檢索viewparameter(我知道我可以用我的臨時存儲用戶id在bean導航系統,但這種方法會大大票友):

String name = "userId"; 
    FacesContext ctx = FacesContext.getCurrentInstance(); 
    ViewDeclarationLanguage vdl = ctx.getApplication().getViewHandler().getViewDeclarationLanguage(ctx, viewId); 
    ViewMetadata viewMetadata = vdl.getViewMetadata(ctx, viewId); 
    UIViewRoot viewRoot = viewMetadata.createMetadataView(ctx); 
    UIComponent metadataFacet = viewRoot.getFacet(UIViewRoot.METADATA_FACET_NAME); 

    // Looking for a view parameter with the specified name 
    UIViewParameter viewParam = null; 
    for (UIComponent child : metadataFacet.getChildren()) { 
     if (child instanceof UIViewParameter) { 
      UIViewParameter tempViewParam = (UIViewParameter) child; 
      if (name.equals(tempViewParam.getName())) { 
       viewParam = tempViewParam; 
       break; 
      } 
     } 
    } 

    if (viewParam == null) { 
     throw new FacesException("Unknown parameter: '" + name + "' for view: " + viewId); 
    } 

    // Getting the value 
    String value = viewParam.getStringValue(ctx); // This seems to ALWAYS be null. 

最後一個想到的是setter方法似乎仍然工作時,setUserId在post上被調用了正確的值。

我完全錯過了解視圖參數的工作方式,或者是否存在某種錯誤?我認爲我的用例應該是極其常見的,並且在框架中有基本的支持。

回答

25

當我搜索周圍時,我得到一個印象,即view參數在閱讀userpage.jsf?userId = 123後應該保留,但事實並非如此。什麼是真正的預期行爲?

此行爲是正確的。 <h:form>生成一個HTML <form>元素,其動作URL爲而不是任何視圖參數。 POST請求只是提交到那個URL。如果你打算在URL中保留視圖參數,那麼基本上有3種方法:

  1. 帶來一些ajax魔法。

    <h:commandButton action="#{userPageController.doAction}" value="post"> 
        <f:ajax execute="@form" render="@form" /> 
    </h:commandButton> 
    

    這樣,最初請求的頁面以及瀏覽器地址欄中的請求URL始終保持不變。

  2. 如果適用(例如,用於頁面到頁面導航),請將其設置爲GET請求並使用includeViewParams=true。您可以使用<h:link><h:button>此:

    <h:button outcome="nextview?includeViewParams=true" value="post" /> 
    

    但是,這有一個EL安全漏洞在鑽嘴魚科的版本比2.1.6老。確保你使用的是Mojarra 2.1.6或更新版本。另見issue 2247

  3. 自己控制動作URL的生成<h:form>。提供自定義ViewHandler(只需擴展ViewHandlerWrapper),其中您在getActionURL()中執行此項工作。

    public String getActionURL(FacesContext context, String viewId) { 
        String originalActionURL = super.getActionURL(context, viewId); 
        String newActionURL = includeViewParamsIfNecessary(context, originalActionURL); 
        return newActionURL; 
    } 
    

    讓它運行,在faces-config.xml註冊,如下所示:

    <application> 
        <view-handler>com.example.YourCustomViewHandler</view-handler> 
    </application> 
    

    這也是什麼OmniFaces<o:form>在做什麼。它支持一個額外的includeViewParams屬性,其中包括在表單的操作URL的所有視圖參數:

    <o:form includeViewParams="true"> 
    

更新:獲得編程當前視圖的視圖參數(這基本上是你的第二個問題)應按如下方式完成:

Collection<UIViewParameter> viewParams = ViewMetadata.getViewParameters(FacesContext.getCurrentInstance().getViewRoot()); 

for (UIViewParameter viewParam : viewParams) { 
    String name = viewParam.getName(); 
    Object value = viewParam.getValue(); 
    // ... 
} 
+0

我認爲第三個是衆所周知的選項。 – kosa 2012-04-27 15:51:34

+0

我可能會用1.來處理url欄問題。關於2:這將是一個乾淨的解決方案來查看參數處理,但它只適用於2頁使用相同的託管bean(我認爲通常是一個不好的選擇),從而使它無用。我很可能最終會在每個鏈接中手動定義參數。 你有什麼想法的底部的代碼不起作用?以編程方式獲取視圖參數。 – 2012-04-27 18:09:18

+0

這是因爲您正在創建全新視圖,而不是使用當前視圖。查看更新的答案。 – BalusC 2012-04-27 18:16:30

0

我是對的,對於解決方案1 ​​<f:ajax execute="@form" render="@form" />到w ORK一個也必須包括像

<f:param name="userId" value="#{userPageController.userId}"/> 

裏面的<h:commandButton>

就像它被描述在https://stackoverflow.com/a/14026995/811046