我最近一直在开发一些JSF应用程序,并且对Web组件API中的不一致感到不安。

我注意到在服务器端代码中的JSF组件对象上调用.getValue()或.getSubmittedValue()时,存在极其不可预测的行为。有时,当我在下拉列表框中调用.getValue()时,我注意到我在选择值之前(即从上一页刷新值开始)获得了该值,其中.getSubmittedValue()得到了我正确的值,例如:

UIInput name = new UIInput(); // This is the control I have in a bean.

public void submit(ActionEvent ae)
{
    someMethod(name.getValue().toString());          // Retrieves the "old" value
    someMethod(name.getSubmittedValue().toString()); // Retrieves the correct value
}

另外,我注意到在表单字段上调用.getSubmittedValue()有时会导致空指针异常,因为该值尚未在组件对象中实例化,在这种情况下,我在这种情况下调用.getValue()正确的值,例如:
HtmlInputText name = new HtmlInputText(); // This is the control I have in a bean.

public void submit(ActionEvent ae)
{
    someMethod(name.getValue().toString());          // Retrieves the correct value
    someMethod(name.getSubmittedValue().toString()); // Throws NullPointerException
}

这仅仅是JSF框架的“怪癖”,还是我错误地使用了API COMPLETELY ?任何对这两种方法的见解将不胜感激。干杯。

最佳答案

由于这是Google搜索getValue与getSubmittedValue的第一结果,我想补充一下,两者之间的区别对于验证(即编写自定义验证器)至关重要

引用getSubmittedValue()的API文档:



资料来源: http://myfaces.apache.org/core11/myfaces-api/apidocs/javax/faces/component/UIInput.html#getSubmittedValue()

这意味着,如果对您尝试访问的绑定(bind)进行了验证/转换,则应调用getValue(),否则必须调用getSubmittedValue()并自己进行解析。这些发生的顺序似乎由它们在用户界面中出现的顺序决定,但我认为这不能保证。即使是这样,您也不应该依靠它,因为UI中的更改字段不会破坏您的代码。

您可以仅通过查看isLocalValueSet()返回的内容来检测是否已完成验证/转换。如果返回true,则说明已完成验证/转换,因此应调用getValue()。否则,您将需要调用getSubmittedValue(),这将为您提供用户输入的原始输入,并且您可能希望将其解析为更有意义的内容。

例如,当调用getValue()时,日历对象将返回Date对象,但是当调用getSubmittedValue()时,则返回String对象。由您的转换器将字符串解析为日期,以便可以对其进行验证。

如果JSF规范中有一种方法可以为我们做到这一点,那就太好了,但AFAIK却没有。如果某些日期需要早于其他日期,并且某些日期仅在某些情况下才需要,则将需要编写多个验证器来处理此问题。因此,它很容易成为一个问题。这类似于您不能对空白字段进行任何类型的验证这一事实,这意味着您不能使该字段成为条件字段。如果对所有字段(即使是空白字段)都进行了验证,则可以编写自定义验证器以引发异常(如果需要的话),而不是不是。使用JSF时有些事情很痛苦。除非/直到它们解决,否则我们只需要处理它们。

在原始帖子中讲这个问题的细节:这里的区别是您在生命周期中所处的位置。 submit方法似乎是按钮的 Action 侦听器,它将其置于生命周期的尽头。操作和操作侦听器在呈现响应之前但在验证之后的“调用应用程序”阶段中触发。如果要使用JSF进行编程,则应该学习和理解生命周期。值得的。

10-06 13:35