为什么第一个AJAX调用会重置我的视图参数?
我不明白为什么第一个ajax调用会导致再次调用视图参数的setter,而随后的每个调用都不会再次调用setter 我有以下简单的视图bean:为什么第一个AJAX调用会重置我的视图参数?,ajax,jsf,mojarra,jsf-2.3,Ajax,Jsf,Mojarra,Jsf 2.3,我不明白为什么第一个ajax调用会导致再次调用视图参数的setter,而随后的每个调用都不会再次调用setter 我有以下简单的视图bean: 封装测试; 导入java.io.Serializable; 导入javax.faces.view.ViewScoped; 导入javax.inject.Named; @命名 @视域 公共类TestController实现可序列化{ 私有静态最终长serialVersionUID=1L; 字符串参数; 公共字符串getParam(){ 返回参数; } 公共
封装测试;
导入java.io.Serializable;
导入javax.faces.view.ViewScoped;
导入javax.inject.Named;
@命名
@视域
公共类TestController实现可序列化{
私有静态最终长serialVersionUID=1L;
字符串参数;
公共字符串getParam(){
返回参数;
}
公共void setParam(字符串参数){
System.out.println(“参数设置为”+param);
this.param=param;
}
}
我还有一个非常基本的.xhtml页面,它只包含一个按钮:
现在,当测试此页面时,我调用https://localhost:8443/test/test.xhtml?param=foo
在我的浏览器中。正如我所料,日志声明视图参数设置为“foo”。现在我正在挣扎的是,当我第一次按下按钮时,日志再次声明param被设置为“foo”,证明setter再次被调用。我不明白为什么ajax请求会再次设置view参数。我还感到困惑的是,任何后续的按钮单击都不会再次调用视图参数的setter,特别是当第一次和所有后续调用看起来完全相同时
因此,我的问题是:
- 为什么视图参数的setter在第一次ajax调用时被调用,而在随后的调用中没有被调用
- 有没有办法防止这种行为
FacesContext.getCurrentInstance().isPostback()
。我知道这一点。当然,它在检测ajax调用的意义上起作用,并使我能够在这种情况下不重置视图参数,但它并不会阻止视图参数的setter首先被调用。这是我理想中想要实现的目标。我还希望自己至少能够理解为什么在第一次ajax调用中对视图参数的处理会有所不同。我想在概念上我还没有理解
编辑2:我在下提交了一份错误报告。快速解决方案
解决此问题的最佳方法是使用withincludeViewParams
设置为true
(setParam
在每个ajax请求上调用;只有在ajax请求中参数可以更改时才使用)
或
@Kukeltje已经说过(这与重写UIViewParameter
的作用相同),因此setParam
方法在开始时只调用一次
解释 基本上是在第一个ajax请求的初始请求期间保存的参数值。在第一个ajax请求之后,值最终丢失 理解这一点的最佳方法可能是逐阶段分析(查看以了解这些方法的作用也很有帮助):
初始请求 恢复视图阶段:没有任何特定内容 应用请求值阶段:
decode
已调用且rawValue
已使用当前参数值设置
流程验证阶段:没有特定的内容
更新模型值阶段:调用setParam
,然后调用UIInput.resetValues()
,将submittedValue
设置为null
调用应用程序阶段:没有特定的内容
呈现响应阶段:setSubmittedValue
(为空)通过rawValue
调用(已设置rawValue;请参阅应用请求值阶段)
第一个Ajax
还原视图阶段:rawValue重新初始化为null
应用请求值阶段:decode
已调用且rawValue
已使用当前参数值设置(参数值为null
)
流程验证阶段:没有特定的内容
更新模型值阶段:setParam
使用submittedValue
调用,该值设置为null
,但在渲染响应阶段再次设置<再次调用code>UIInput.resetValues(),并将submittedValue
设置为null
调用应用程序阶段:没有特定的内容
渲染响应阶段:setSubmittedValue
再次被调用并设置为rawValue
,即null
下面的每个ajax请求
submittedValue
和rawValue
为null
因此所有恢复参数值的可能性都被破坏<代码>设置参数不再被调用
所有解决方案
- 重写
方法不再执行任何操作,因此encodeAll
将永远重置值(请参阅)UIInput.resetValues()
- 使用
(没有o:viewParam
变量)rawValue
- 使用
o:form
重写UIViewParameter 要覆盖
UIViewParameter
,请创建一个扩展UIViewParameter
的类,并将其添加到faces config.xml
:
<component>
<component-type>javax.faces.ViewParameter</component-type>
<component-class>com.example.CustomUIViewParameter</component-class>
</component>
javax.faces.ViewParameter
com.example.CustomUIViewParameter
你在概念上没有误解。我也不明白
我目前仍在研究为什么在第一次调用setter,并且只在第一次ajax回调中调用setter。我早就料到了
<o:viewParam id="param" name="param" value="#{testController.param}"/>
<context-param>
<param-name>javax.faces.INTERPRET_EMPTY_STRING_SUBMITTED_VALUES_AS_NULL</param-name>
<param-value>true</param-value>
</context-param>
@Override
public String getSubmittedValue() {
return submittedValue;
}
@Override
public void setSubmittedValue(Object submittedValue) {
this.submittedValue = (String) submittedValue; // Don't delegate to statehelper to keep it stateless.
}
@Override
public Object getSubmittedValue() {
return getStateHelper().get(PropertyKeys.submittedValue);
}
/**
* PENDING (docs) Interesting that submitted value isn't saved by the parent
* @param submittedValue The new submitted value
*/
@Override
public void setSubmittedValue(Object submittedValue) {
getStateHelper().put(PropertyKeys.submittedValue, submittedValue);
}