JSF Ajax调用应用程序未执行?

JSF Ajax调用应用程序未执行?,ajax,jsf,jsf-2,Ajax,Jsf,Jsf 2,我有一个简单的facelets页面: <!DOCTYPE html> <html xmlns:h="http://xmlns.jcp.org/jsf/html" xmlns:f="http://xmlns.jcp.org/jsf/core"> <h:head> <title>Index</title> </h:head> <h:body> <h:form>

我有一个简单的facelets页面:

<!DOCTYPE html>
<html xmlns:h="http://xmlns.jcp.org/jsf/html"
      xmlns:f="http://xmlns.jcp.org/jsf/core">
<h:head>
    <title>Index</title>
</h:head>
<h:body>
    <h:form>
        <h:inputText id="firstname" value="#{fooBar.firstname}">
            <f:ajax event="keyup" render="echo" execute="myCommandButton"/>
        </h:inputText>
        <h:commandButton value="Submit" action="#{fooBar.fooBarAction()}" id="myCommandButton"/>
    </h:form>
    <br/>
    <h:outputText id="echo" value="#{fooBar.firstname}"/>
</h:body>
</html>
因此,每当我在inputText字段中键入内容时,我希望看到文本Foo-bar操作被执行,但事实并非如此。我错过了什么

编辑:我为什么期待这种行为? 我正在研究这本书,书中指出:

JSF2.0将JSF生命周期分为两部分:执行和呈现

执行包括:还原视图->应用请求值->进程 验证->更新模型值->调用应用程序

当JSF在服务器上执行组件时,它:

-转换并验证组件的值(如果组件是输入)

-将有效的输入值推送到模型(如果组件连接到bean属性)

-执行操作和操作侦听器(如果组件是操作)

所以在这里,myCommand按钮应该被执行,不是吗?组件的执行意味着要执行的动作

编辑#2

此引文来源于《JavaServer Faces完整参考》

如果未指定侦听器,则将调用的唯一操作 在调用应用程序阶段,将是与 执行属性中列出的ActionSource组件


据我所知,在我的示例中,我有一个实现ActionSource接口(MyCommand Button)的组件,应该执行该组件的action属性。但它不是?

在每个关键点上要调用的操作和/或actionListener必须在
f:ajax
方面定义。您在下面的
h:commandButton
中定义了您的操作。JSF没有看到ajax方面和按钮之间的任何连接。除了技术原因外,至少有两个原因使这种行为合理:

  • 表单中可以有多个命令按钮。事实上,你通常至少有两个选项:“保存”和“取消”。是否应在每次按键时触发这两个动作?按哪个顺序?没有办法自动决定,因此JSF决定通过强制您在AJAX方面定义操作来避免这个问题。请注意:您的表单可能包含一个由100行组成的表,每行带有“删除”、“编辑”和“在此行之后插入新行”按钮。应该执行哪个操作
  • 输入字段可能有多个方面。例如,可以为事件“keyup”和“blur”定义不同的方面。如果您定义了多个方面,您可能希望它们调用不同的后端bean方法。您不希望他们调用表单的任何其他命令按钮。请记住,它可能是“取消”按钮,如果在每次按键时都触发,则会有点不方便
因此,您从核心JSF书籍中引用的语句是正确的。执行每个操作和actionListener。你的错误是,你在心里把范围扩大到了整个表单。相反,JSF只查看围绕AJAX方面的组件


JavaServer Faces Complete Reference的引用在我看来完全是错误的。当既没有指定操作也没有指定actionListener时,JSF的“调用应用程序”阶段不会执行任何操作。输入被发送到服务器,经过验证,存储在后端bean中,用于再次呈现页面。但是没有调用任何操作,因为您没有指定要调用的操作。
execute
属性基本上告诉JSF在回发期间JSF生命周期中要处理哪些组件。也就是说,它基本上告诉JSF它必须为哪些组件执行应用请求值、流程验证、更新模型值和调用应用程序阶段。应用请求值阶段将收集(解码)提交的HTML表单(输入和按钮)值。验证阶段将对提交的值运行转换/验证。更新模型值阶段将在备份bean中设置提交/转换/验证的值。调用应用程序阶段将执行提交的操作。请注意,关键是JSF将根据提交的HTML表单值来完成这一切

换句话说,
execute
属性完全是服务器端的。这并不像你想象的那样是客户端。您似乎期望它告诉webbrowser提交指定的组件,就好像您在单击它一样。事实并非如此。按钮值仅在JSF生命周期中实际被按下/单击/提交时才被处理

如果按钮在
execute
属性中指定,并且JSF在处理生命周期期间确定按钮值实际上没有提交(即,它在HTTP请求参数映射中完全不存在),那么JSF在应用请求值阶段根本不会将操作事件排队。因此,在调用应用程序阶段不会调用任何内容

当触发
事件时,实际上是作为操作源的封闭组件。因此,您应该将所需的操作侦听器挂接到它上。您可以使用
listener
属性进行此操作

<h:form>
    <h:inputText id="firstname" value="#{fooBar.firstname}">
        <f:ajax event="keyup" listener="#{fooBar.keyupListener}" render="echo" />
    </h:inputText>
    <h:commandButton value="Submit" action="#{fooBar.fooBarAction}" id="myCommandButton"/>
</h:form>
另见:

@BalusC我读了这个答案,但我找不到你在哪里解释为什么不调用已执行组件的action属性?@BalusC在h:commandButton中也没有execute属性?我不确定这个答案是否与我的问题有关。嗨@BalusC,请看我的编辑?我希望commandButton将被“执行”,其中“执行”阶段包括触发组件的操作。显然,情况并非如此。你能对我问题的编辑2中的JavaServer Faces Complete Reference中的语句发表评论吗?我已经对编辑2中的引用发表了评论。我
<h:form>
    <h:inputText id="firstname" value="#{fooBar.firstname}">
        <f:ajax event="keyup" listener="#{fooBar.keyupListener}" render="echo" />
    </h:inputText>
    <h:commandButton value="Submit" action="#{fooBar.fooBarAction}" id="myCommandButton"/>
</h:form>
@ManagedBean
@RequestScoped
public class FooBar {

    private String firstname;

    public void keyupListener() {
        System.out.println("Keyup listener being executed");
    }

    public void fooBarAction() {
        System.out.println("Foo bar action being executed");
    }

    // ...
}