2014-07-07 25 views
2

我一直在我的應用程序中使用preRenderView(+重定向和跳過回發黑客),我試圖用JSF2.2附帶的viewAction替換它(MyFaces 2.2.4)。然而,我發現它早於命令actionListener觸發,並且它對我的目的來說沒有任何用處。例如:JSF 2.2:viewAction觸發器早於actionListener和動作

import java.io.Serializable; 

import javax.faces.bean.ManagedBean; 
import javax.faces.bean.ViewScoped; 

@ManagedBean 
@ViewScoped 
public class TestBean2 implements Serializable { 

    int count = 0; 

    public void actionFunc() { 
    System.out.println(count); 
    } 

    public String addCount() { 
    count++; 
    return null; 
    } 

    public int getCount() { 
    return count; 
    } 

    public void initView() { 
    System.out.println("initView"); 
    } 

    public void setCount(int count) { 
    this.count = count; 
    } 

} 

,然後一個非常簡單的.xhtml:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" 
    "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> 

<html xmlns="http://www.w3.org/1999/xhtml" xmlns:ui="http://java.sun.com/jsf/facelets" xmlns:h="http://java.sun.com/jsf/html" 
    xmlns:f="http://java.sun.com/jsf/core" xmlns:pt="http://xmlns.jcp.org/jsf/passthrough" xmlns:jsf="http://xmlns.jcp.org/jsf" 
    xmlns:t="http://myfaces.apache.org/tomahawk" xmlns:p="http://primefaces.org/ui"> 

<f:metadata> 
    <f:event type="preRenderView" listener="#{testBean2.initView}" /> 
    <f:viewAction action="#{testBean2.actionFunc}" onPostback="true" /> 
</f:metadata> 

<ui:composition template="/WEB-INF/template.xhtml"> 
    <ui:define name="title">Test</ui:define> 

    <ui:define name="content"> 
    #{testBean2.count} 
     <h:form> 
     <h:commandButton styleClass="btn btn-primary" action="#{testBean2.addCount}" value="addCount"> 
     </h:commandButton> 
    </h:form> 
    </ui:define> 
</ui:composition> 
</html> 

所以addCount()的System.out輸出始終是1後面所再現的觀點是什麼,因爲actionFunc()始終觸發在addCount()之前。

如果我想要做類似的事情,如果(count == 3)爲重定向做一個返回「newpage」,它對於這樣的決定結束方式太早了。我可以在initView()中執行檢查並執行ConfigurableNavigationHandler.performNavigation(「newpage」),但這正是我試圖用JSF 2.2消除的那種黑客。

因此,它似乎像viewAction是無用的,如果我希望它與任何值,我將改變與行動或actionListener。它應該像這樣工作嗎?

謝謝!

+0

這個問題聽起來很有趣,你讀過關於'f:viewAction'標籤的[docs](http://www.oracle.com/technetwork/articles/java/jsf22-1377252.html)嗎?還有其他一些屬性,例如'phase'或'immediate',給他們一個嘗試,如果你碰巧實現它,不要忘記發佈一個答案! –

+0

嗨。已經嘗試過。階段默認情況下已經是最新的:「APPLY_REQUEST_VALUES,PROCESS_VALIDATIONS,UPDATE_MODEL_VALUES或INVOKE_APPLICATION。默認爲INVOKE_APPLICATION。」 immediate =「true」使其成爲APPLY_REQUEST_VALUES,它現在甚至更早。 – JPlatinum

+0

我開始寫評論,但我最終用我認爲它的目的是工作的方式寫了一個完整的答案。希望它對你有用。 –

回答

1

preRenderView事件is executed開頭的RENDER_RESPONSE階段。但是,viewAction標籤不允許該階段。我想你的情況你應該在你的操作方法(TestBean2#addCount)中處理重定向,並且忘記使用事件,因此對剛剛初始化的值執行檢查是沒有意義的(這就是你對preRenderView方法,當您第一次加載視圖時)。在執行完邏輯之後將其檢入到操作方法中,似乎是它的自然方式。

我相信事件也可以用來檢查條件,但它們更多的與會話和應用程序狀態有關,而與當前視圖值無關。我的意思是,你能做到這一點來處理你的店鋪沒有項目可重定向之前,你的觀點被渲染:

public String checkItemsAvailable() { 
    if (!dao.itemsAvailable()){ 
     return "noItemsAvailable"; 
    } 
    return null; 
} 

但基於條件的重定向是在當前視圖正在評估,演藝吧在操作方法是最好的一段路要走:

public void addCount() { 
    count++; 
    if (count>3){ 
     FacesContext.getCurrentInstance() 
      .getExternalContext().redirect("index.xhtml"); 
    } 
} 

參見:

+0

嗨。感謝你的回答。 在實際情況下,action方法實際上存在於SessionScoped bean內部,並更改其中的值(例如模式A/B切換)並返回到相同的視圖(它總是返回null)。我的意圖是讓每個頁面的viewAction檢查並做相應的事情(如重定向)。因此,我無法在操作方法中硬編碼非空返回值。 與現在的情況相比,viewAction方法始終可以看到與preRenderView sess相比,後者的值只有一步,這是正確的值。 – JPlatinum

+0

此外,進一步的測試顯示動作是否轉到不同的視圖,然後在動作之後觸發viewAction。但是,如果操作返回到相同的視圖(即,返回null;),那麼viewAction(同樣,使用postback = true)將在操作之前觸發。 – JPlatinum

+0

我不知道你的具體情況是什麼,但是,看到viewaction文檔,我推斷你可以使用它來重定向基於在當前請求之前設置的條件。如果您想要重定向基於當前請求,請在當前按鈕方法內使用重定向。無論如何,您總是可以選擇像使用prerenderview一樣進行操作。 –