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