我最近一直在开发一些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文档:
这仅在解码和验证阶段之间或者在组件验证未成功时才为非空.转换和验证成功后,(转换的)值将存储在此组件的本地"value"属性中,并且提交的值将重置为null.
资源: http://myfaces.apache.org/core11/myfaces-api/apidocs/javax/faces/component/UIInput.html#getSubmittedValue()
这意味着如果对您尝试访问的绑定进行了验证/转换,则应调用getValue(),否则您必须调用getSubmittedValue()并自行解析它.这些发生的顺序似乎取决于它们在UI中出现的顺序,但我不认为这是有保证的.即使它是,你也不应指望它,因为UI中的更改字段不应该破坏你的代码.
您可以通过查看isLocalValueSet()返回的内容来检测验证/转换是否已完成.如果它返回true,那么valdation/conversion已经完成,所以你应该调用getValue().否则你需要调用getSubmittedValue()并且它会给你用户输入的原始输入,你可能想要将它解析成更有意义的东西.
例如,日历对象在调用getValue()时返回Date对象,但在调用getSubmittedValue()时返回String对象.由转换器将字符串解析为Date,以便进行验证.
如果JSF规范有一个方法可以为我们做到这一点,那将是很好的,但AFAIK却没有.如果某些日期需要在其他日期之前,并且某些日期仅在某些情况下需要,则需要编写几个验证器来处理此问题.所以它很容易成为一个问题.这类似于您无法对空白字段进行任何类型的验证,这意味着您无法有条件地要求该字段.如果验证是在所有字段上运行的,即使是空白字段,也可以编写自定义验证器,以便在需要时抛出异常,而不是.JSF有些东西只是一种痛苦; 除非他们得到修复,否则我们只需处理它们.
在原帖中谈到问题的具体细节:这里的区别在于您在生命周期中的位置.该submit
方法看起来像一个按钮的动作监听器,它将其置于生命周期的末尾; 动作和动作侦听器在渲染响应之前的"调用应用程序"阶段中触发,但在验证之后.如果您要在JSF中编程,您应该学习并理解生命周期.这值得花时间.
引用EditableValueHolder.getSubmittedValue上的文档:
返回此组件的submittedValue值.此方法只应由此组件的encodeBegin()和/或encodeEnd()方法或其对应的Renderer使用.
通常,您甚至不会调用getValue.相反,组件的value属性应绑定到您的模型(可能是bean).您的业务逻辑将与模型交互,而不是与组件交互.
如果未将提交的值设置为值,那么我猜测某些验证失败了.唯一的问题是你的事件被解雇了.这里有两个猜测问题:
您有一个对组件对象的陈旧引用.
您已在UICommand上设置了immediate属性,这意味着在组件处于不适当状态的阶段触发该事件.
无法确定所提供的信息.