22

我最近一直在开发一些 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?对这两种方法的任何见解将不胜感激。干杯。

4

4 回答 4

32

由于这是在 Google 中搜索 getValue 与 getSubmittedValue 的第一结果,我想补充一点,它们之间的区别在验证中至关重要(即在编写自定义验证器时)

引用 getSubmittedValue() 的 API 文档:

这仅在解码和验证阶段之间或组件验证未成功时为非空值。一旦转换和验证成功,(转换后的)值将存储在该组件的本地“value”属性中,并且提交的值重置为 null。

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

这意味着如果您尝试访问的绑定已经进行了验证/转换,您应该调用 getValue() 否则您将不得不调用 getSubmittedValue() 并自己处理解析它。这些发生的顺序似乎是由它们在 UI 中出现的顺序决定的,但我认为这不能保证。即使是这样,您也不应该指望这一点,因为 UI 中的更改字段不应该破坏您的代码。

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

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

如果 JSF 规范有一种方法可以为我们做到这一点,那就太好了,但 AFAIK 没有。如果某些日期需要在其他日期之前,并且某些仅在某些情况下需要,则需要编写几个验证器来处理这个问题。所以它很容易成为一个问题。这类似于您不能对空白字段进行任何类型的验证,这意味着您不能有条件地要求该字段。如果对所有字段(甚至是空白字段)都运行了验证,则可以编写自定义验证器来抛出异常(如果它应该被要求而不是)。JSF 有一些东西只是一种痛苦。除非/直到它们被修复,我们只需要处理它们。

在原始帖子中谈论问题的细节:这里的区别在于您在生命周期中所处的位置。该submit方法看起来像是一个按钮的动作监听器,将其置于生命周期的末尾;动作和动作监听器在渲染响应之前但在验证之后的“调用应用程序”阶段触发。如果您打算使用 JSF 进行编程,您应该学习并理解生命周期。值得花时间。

于 2009-07-17T20:48:47.803 回答
6

引用EditableValueHolder.getSubmittedValue上的文档:

返回该组件的提交值。此方法应仅由该组件的 encodeBegin() 和/或 encodeEnd() 方法或其对应的 Renderer 使用。

通常,您甚至不会调用getValue。相反,组件的value属性应该绑定到您的模型(也许是一个 bean)。您的业​​务逻辑将与模型交互,而不是与组件交互。

如果提交的值没有被设置为值,那么我猜想某些验证失败了。唯一的问题是你的事件被触发了。这里有两个问题的猜测:

  • 您对组件对象有一个过时的引用。
  • 您已经在UICommand上设置了immediate属性,这意味着在组件处于不适当状态的阶段触发事件。

无法确定所提供的信息。

于 2008-11-04T00:23:34.293 回答
0

我在基于 JSF 的 xpage 上工作,所以.. 可能是一样的...

无论如何,getSubmittedValue(); 始终返回您在 firebug/chrome 开发人员网络选项卡中看到的内容。那是发送数据包中的值。我在标题选项卡中显示(chrome),在表单数据部分中,名为 $$xspsubmitvalue。

另一方面,getValue() 是特定于组件的。<-- 这里不是 100% 确定。

于 2014-08-07T18:16:34.380 回答
0

TL;DR答案:

UIViewRoot viewRoot = context.getViewRoot();
UIInput input = (UIInput)viewRoot.findComponent(":form:inputID");

String inputValueString;

if (input.isLocalValueSet()) {
  inputValueString = (String)input.getValue(); //validated and converted already
} else {
  inputValueString = (String)input.getSubmittedValue(); //raw input
}

或者至少这就是其他答案所说的......

只需使用.getSubmittedValue()并处理必须转换原始输入的后果(如有必要,如果该原始输入需要转换)。.getValue()即使使用上面的代码,在这方面也被破坏了。如果您使用它,它会延迟提交的值,这是不可接受的。

于 2017-10-10T21:20:58.253 回答