我有一个登录页面:
<h:form id="f_login" >
<f:passThroughAttribute name="data-ajax" value="false" />
<h:messages id="message" showDetail="false" errorClass="error_msg" fatalClass="success_msg" infoClass="info_msg" warnClass="warning_msg" />
<h:inputText value="#{loginWEB.user.email}" >
<f:passThroughAttribute name="placeholder" value="Email" />
<f:ajax event="change" execute="@this" />
</h:inputText>
<h:inputSecret value="#{loginWEB.user.senha}" autocomplete="off" >
<f:passThroughAttribute name="placeholder" value="Senha" />
<f:ajax event="change" execute="@this" />
</h:inputSecret>
<h:commandButton id="btn_login" value="Login" action="#{loginWEB.login()}" >
<f:passThroughAttribute name="data-theme" value="g" />
<f:ajax render="message" />
</h:commandButton>
</h:form>
Run Code Online (Sandbox Code Playgroud)
使用此操作方法:
public void login() {
try {
FacesContext context = FacesContext.getCurrentInstance();
if (...) { //Verify email and password
context.getExternalContext().redirect("/templates/main.xhtml");
}
else {
FacesMessage message = new FacesMessage("Invalid email or password");
message.setSeverity(FacesMessage.SEVERITY_ERROR);
context.addMessage(null, message);
}
} catch (Exception e) {
Logger.getLogger(LoginWEB.class.getName()).log(Level.SEVERE, null, e);
}
}
Run Code Online (Sandbox Code Playgroud)
提交此表单有时会导致JS错误:
httpError:Http Transport返回0状态代码.这通常是混合ajax和完整请求的结果.出于性能和数据完整性的原因,这通常是不期望的.
我不明白我做错了什么.这是怎么造成的,我该如何解决?
如果其中一个输入字段在更改时仍然保持焦点并且通过鼠标或[输入]键按下提交按钮而不是标记为(以便输入字段的更改事件首先触发),则确实存在该特定错误的机会.在两个ajax请求之间将发生竞争条件:由输入字段的更改事件触发的请求和由提交按钮的操作事件触发的另一个请求.在这种情况下,未确定哪一个会首先击中服务器.
在JSF中,ajax请求排队.因此,如果一个命中服务器,另一个将等到它返回并完成.当提交按钮的ajax请求是第一个命中服务器的请求时,将发生您的问题.如果登录成功,服务器将返回执行重定向的指令.在完成ajax请求期间,此重定向由JavaScript处理.在此之后,队列中的下一个ajax请求(如果有的话)将被触发(尽管重定向!这反过来IMO在JSF的ajax引擎中出现设计错误,但除此之外).但是,由于文档已通过重定向更改,因此第二个ajax请求未命中,导致此错误.
总而言之,这种ajax形式的方法有点奇怪.输入字段和提交按钮分别通过ajax而不是通过提交按钮一次性发送它们的值.它看起来非常像您最初<f:ajax>
在提交按钮中有这个,但您认为未处理输入值,因此您决定<f:ajax>
向这些输入字段添加另一个.
这不是完全正确的方法.您应该execute="@form"
在提交按钮中使用,以指示它执行(处理)整个表单.
因此,所以:
<h:form id="f_login">
<f:passThroughAttribute name="data-ajax" value="false" />
<h:messages id="message" showDetail="false" errorClass="error_msg" fatalClass="success_msg" infoClass="info_msg" warnClass="warning_msg" />
<h:inputText value="#{loginWEB.user.email}">
<f:passThroughAttribute name="placeholder" value="Email" />
</h:inputText>
<h:inputSecret value="#{loginWEB.user.senha}" autocomplete="off">
<f:passThroughAttribute name="placeholder" value="Senha" />
</h:inputSecret>
<h:commandButton id="btn_login" value="Login" action="#{loginWEB.login}">
<f:passThroughAttribute name="data-theme" value="g" />
<f:ajax execute="@form" render="message" />
</h:commandButton>
</h:form>
Run Code Online (Sandbox Code Playgroud)
这样一次只能激发一个ajax请求,消除了竞争条件的风险.