JSF组件使用binding
,支持bean为View scope
。该组件设置了validator
和valueChangeListener
。当组件的值改变时,部分请求被发送到服务器。 validator
和valueChangListener
被多次调用,但在请求中不会被调用一次。
如何在请求期间调用它们一次?
如果删除binding
,则会正确调用一次方法。
但是有可能不删除绑定并使侦听器被调用一次吗?
下一个使用的代码示例:
<h:inputText id="txt"
validator="#{myBean.validateValue}"
valueChangeListener="#{myBean.valueChanged}"
binding="#{myBean.txtInput}">
<f:ajax event="valueChange"
execute="@this"
render="@this"/>
</h:inputText>
@ViewScoped
@ManagedBean
public class MyBean {
private HtmlInputText txtInput;
public void valueChanged(ValueChangeEvent ve) {
...
}
public void validateValue(FacesContext context, UIComponent component, Object value) {
...
}
public HtmlTextInput getTxtInput() {
return txtInput;
}
public void setTxtInput(HtmlTextInput txtInput) {
this.txtInput = txtInput;
}
}
如果actionListener
和commandLink
组件使用绑定且支持bean具有View scope
,则会发生同样的问题。
答案 0 :(得分:-1)
可能的解决方案可能只是覆盖UIInput
和UICommand
用来存储validators
和listeners
的类。该课程为javax.faces.component.AttachedObjectListHolder
。
此类直接将新listener
添加到支持列表,而不检查是否已存在相同的listener
。
因此,解决方案是检查listener
是否存在,然后不添加它。
从javax.faces.component.AttachedObjectListHolder
获取jsf-api-2.1.<x>-sources.jar
并将其添加到项目中的相应包中。将方法add
替换为以下方法:
void add(T attachedObject) {
boolean addAttachedObject = true;
if (attachedObject instanceof MethodExpressionActionListener
|| attachedObject instanceof MethodExpressionValueChangeListener
|| attachedObject instanceof MethodExpressionValidator) {
if (attachedObjects.size() > 0) {
StateHolder listener = (StateHolder) attachedObject;
FacesContext context = FacesContext.getCurrentInstance();
Object[] state = (Object[]) listener.saveState(context);
Class<? extends StateHolder> listenerClass = listener.getClass();
for (Object tempAttachedObject : attachedObjects) {
if (listenerClass.isAssignableFrom(tempAttachedObject.getClass())) {
Object[] tempState = (Object[]) ((StateHolder) tempAttachedObject).saveState(context);
if (((MethodExpression) state[0]).getExpressionString().equals(((MethodExpression)tempState[0]).getExpressionString())) {
addAttachedObject = false;
break;
}
}
}
}
}
clearInitialState();
if (addAttachedObject) {
attachedObjects.add(attachedObject);
}
}
在验证器之后,即使使用组件绑定和“查看”,“会话”或“应用程序”范围,valueChangeListeners和actionListeners也只会触发一次。