JSF中的即時屬性通常被誤解。 如果您不相信我,請查看Stack Overflow 。 造成這種混亂的部分原因可能是輸入(即<h:inputText />)和命令(即<h:commandButton />)組件都立即可用,每個組件對JSF生命周期的影響都不同。
這是標準的JSF生命周期:

出于本文的目的,我假設您熟悉JSF生命周期的基礎知識。 如果您需要簡介或內存更新,請查看Java EE 6教程– JavaServer Faces應用程序的生命周期 。
注意:本文中的代碼示例適用于JSF 2(Java EE 6),但是其原理與JSF 1.2(Java EE 5)相同。
在Command組件上為Instant = True
在標準 JSF生命周期中,在“ 調用應用程序”階段評估Command組件上的action屬性。 例如,假設我們有一個User實體/ bean:
public class User implements Serializable {@NotBlank@Length(max = 50)private String firstName;@NotBlank@Length(max = 50)private String lastName;/* Snip constructors, getters/setters, a nice toString() method, etc */
}
還有一個UserManager用作我們的托管bean:
@SessionScoped
@ManagedBean
public class UserManager {private User newUser;/* Snip some general page logic... */public String addUser() {//Snip logic to persist newUserFacesContext.getCurrentInstance().addMessage(null,new FacesMessage("User " + newUser.toString() + " added"));return "/home.xhtml";}
還有一個基本的Facelets頁面newUser.xhtml ,以呈現視圖:
<h:form><h:panelGrid columns="2"><h:outputText value="First Name: " /><h:panelGroup><h:inputText id="firstName"value="#{userManager.newUser.firstName}" /><h:message for="firstName" /></h:panelGroup><h:outputText value="Last Name: " /><h:panelGroup><h:inputText id="lastName" value="#{userManager.newUser.lastName}" /><h:message for="lastName" /></h:panelGroup></h:panelGrid><h:commandButton value="Add User" action="#{userManager.addUser()}" />
</h:form>
所有這些結合起來產生了這種可愛的形式:

當用戶單擊“ 添加用戶”按鈕時,將在“ 調用應用程序”階段調用 #{userManager.addUser} 。 這是有道理的,因為我們希望在持久保存輸入字段之前對它們進行驗證,轉換并將其應用于newUser。
現在,讓我們在頁面上添加一個“取消”按鈕,以防用戶改變主意。 我們將在頁面中添加另一個<h:commandButton />:
<h:form><!-- Snip Input components --> <h:commandButton value="Add User" action="#{userManager.addUser()}" /><h:commandButton value="Cancel" action="#{userManager.cancel()}" />
</h:form>
還有UserManager的cancel()方法:
public String cancel() {newUser = new User();FacesContext.getCurrentInstance().addMessage(null,new FacesMessage("Cancelled new user"));return "/home.xhtml";
}
看起來不錯吧? 但是,當我們實際嘗試使用“取消”按鈕時,會收到錯誤消息,提示您需要輸入名字和姓氏:

這是因為直到流程驗證階段之后發生的調用應用程序階段才調用 #{userManager.cancel} 。 由于我們沒有輸入名字和姓氏,因此在調用#{userManager.cancel}之前驗證失敗,并且在“ 過程驗證”階段之后呈現響應。
我們當然不希望最終用戶在取消之前輸入有效用戶! 幸運的是,JSF在Command組件上提供了即時屬性。 當直接設置為true的命令組件上,行動調用的應用請求值階段:

這非常適合我們的“取消”用例。 如果我們將Instant = true添加到Cancel,則在進行任何驗證之前,將在Apply Request Values階段調用# {userManager.cancel} 。
<h:form> <!-- Snip Input components --><h:commandButton value="Add User" action="#{userManager.addUser()}" /><h:commandButton value="Cancel" action="#{userManager.cancel()}" immediate="true" />
</h:form>
因此,現在單擊“取消”時,將在“ 應用請求值”階段中調用#{userManager.cancel} ,并通過預期的取消消息返回首頁。 沒有驗證錯誤!

輸入組件也具有即時屬性,該屬性還將其所有邏輯移至“ 應用請求值”階段。 但是,其行為與Command組件略有不同,特別是取決于對Input組件的驗證是否成功。 我的下一篇文章將介紹Input組件上的Instant = true 。 現在,這里是JSF生命周期如何受到影響的預覽:


參考: JSF on Java博客上的 JSF和“立即”屬性–命令組件,來自我們的JCG合作伙伴 Jerry Orr。
翻譯自: https://www.javacodegeeks.com/2012/01/jsf-and-immediate-attribute-command.html