【问题标题】:httpError: The Http Transport returned a 0 status codehttpError:Http 传输返回 0 状态码
【发布时间】:2014-07-01 17:50:32
【问题描述】:

我有一个登录页面:

<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>

使用此操作方法:

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);
    }
}

提交此表单有时会导致 JS 错误:

httpError:Http 传输返回 0 状态代码。这通常是混合 ajax 和完整请求的结果。出于性能和数据完整性的原因,这通常是不受欢迎的。

我不明白我做错了什么。这是如何引起的,我该如何解决?

【问题讨论】:

    标签: ajax jsf


    【解决方案1】:

    如果其中一个输入字段在更改时仍然具有焦点,并且通过鼠标或 [enter] 键而不是按选项卡按下提交按钮,则确实有可能出现该特定错误(以便输入字段的更改事件首先触发)。两个 ajax 请求之间会发生竞争条件:一个由输入字段的更改事件触发,另一个由提交按钮的操作事件触发。正是在这种情况下,谁会先访问服务器。

    在 JSF 中,ajax 请求是queued。因此,如果一个命中服务器,另一个将等到它返回并完成。当提交按钮的 ajax 请求是第一个到达服务器的请求时,就会出现您的问题。如果登录成功,服务器将返回执行重定向的指令。在完成 ajax 请求期间,此重定向由 JavaScript 处理。在此之后,队列中的下一个 ajax 请求(如果有)将被触发(尽管重定向!这反过来又是 IMO JSF 的 ajax 引擎中的设计错误,但除此之外)。但是,由于重定向改变了文档,导致第二个ajax请求未命中,导致这个错误。

    总而言之,这种ajax形式的做法有些奇怪。输入字段和提交按钮每个都通过 ajax 单独发送它们的值,而不是通过提交按钮一次性发送。看起来很像您最初在提交按钮中有 &lt;f:ajax&gt;,但您认为输入值没有被处理,因此您决定在这些输入字段中添加另一个 &lt;f:ajax&gt;。

    这并不完全正确。您应该在提交按钮中使用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>
    

    这样一次只会触发一个 ajax 请求,消除了竞争条件的风险。

    【讨论】:

    • 如果我使用&lt;f:ajax disabled="true"/&gt;,因为我正在使用表单下载文件呢?
    【解决方案2】:

    我终于找到了真正的问题。

    在验证之后和重定向之前,我在会话中放置了一些变量。 但是我要列出一个对象列表,而且要花很长时间。

    可能 jsf 仍在等待返回执行 ajax 请求,在完成之前我正在刷新页面,导致错误。

    我删除了它,现在一切都很好了^^

    非常感谢@BalusC 和@bhdrk 向我展示了正确的使用方法。

    【讨论】:

      【解决方案3】:

      只需将 execute="@form" 添加到 就可以了。

      <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>
      

      【讨论】:

      • 现在它并没有停止页面,但是如果我第一次尝试登录需要很长时间,大约需要 6 ~ 8 秒来重定向,如果我在重定向之前手动刷新页面它会显示具有相同错误的消息。如果我注销并重试,它会重定向非常快。
      猜你喜欢
      • 2017-10-09
      • 1970-01-01
      • 1970-01-01
      • 2011-01-01
      • 2017-01-16
      • 2015-01-12
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多