JSF2:动作和动作监听器

Posted

技术标签:

【中文标题】JSF2:动作和动作监听器【英文标题】:JSF2: action and actionListener 【发布时间】:2012-01-30 18:39:44 【问题描述】:

来自 BalusC 的这个答案 Differences between action and actionListener, Use actionListener if you want have a hook before the real business action get executed, e.g. to log it, and/or to set an additional property (by <f:setPropertyActionListener>,。但是,当我决定编写一些代码来测试它时,结果有点不同。这是我的小代码

<h:form id="form"> 
   <h:panelGroup id="mygroup">
     <p:dataTable id="mytable" value="#viewBean.foodList" var="item">
         <p:column>
             #item
         </p:column>
         <p:column>
             <p:commandButton value="delete" 
                        action="#viewBean.delete"
                        update=":form:mygroup">
                 <f:setPropertyActionListener target="#viewBean.selectedFood"
                                              value="#item"/>
             </p:commandButton>
         </p:column>
      </p:dataTable>
   </h:panelGroup>
</h:form>

这是我的豆子

@ManagedBean
@ViewScoped
public class ViewBean 
    private List<String> foodList;
    private String selectedFood;

    @PostConstruct
    public void init()

        foodList = new ArrayList<String>();
        foodList.add("Pizza");
        foodList.add("Pasta");
        foodList.add("Hamburger");
    

    public void delete()
        foodList.remove(selectedFood);
    
    //setter, getter...

根据 BalusC,actionListener 在这里更合适,但我的示例显示否则

上面的代码在action 上工作得很好,但是如果我切换到actionListener,那么它就不太工作了。使用actionListener 删除此表的条目需要单击两次,而如果我使用action,则每次单击按钮时都会删除条目。我想知道是否有任何 JSF 专家可以帮助我理解 actionactionListener

注意如果我切换到actionListener,我的delete方法变成public void delete(ActionEvent actionEvent)

【问题讨论】:

它是特定于 primefaces 的,还是与 &lt;h:commandButton&gt; 相同? @mrembisz:我确实使用了p:commandButton 中的update,所以我认为有一个与primefaces 相关,但我不是100% 确定。将尝试深入研究。 @mrembisz:J4mes 先生确实确认 h:commandButton 表现出相同的行为。 【参考方案1】:

您将actionactionListener 混淆了。 actionListener 总是在 action 之前运行。如果有多个动作侦听器,则它们以与注册时相同的顺序运行。这就是为什么当您使用actionListener 调用业务操作并使用&lt;f:setPropertyActionListener&gt; 设置(准备)将由业务操作使用的属性时,它无法按预期工作。此问题已在您之前的问题Is this Primefaces bug or Mojarra/MyFaces bug 中指出并修复。

delete() 方法中的任何内容显然都是业务操作,应该由action 调用。业务操作通常会调用 EJB 服务,并在必要时设置最终结果和/或导航到不同的视图。

【讨论】:

【参考方案2】:

我使用原始 JSF 的标签 &lt;h:commandButton&gt; 尝试了您的示例,但我也遇到了同样的症状。我相信如果您指定actionListener 属性,同时用&lt;f:setPropertyActionListener&gt; 声明另一个侦听器,则actionListener 属性中的侦听器将在另一个之前触发。

更新:我用以下代码测试我的假设:

把你的delete 函数改成这个:

public void delete()
    this.selectedFood = "Chicken";
    //foodList.remove(selectedFood);

&lt;h:panelGroup id="mygroup"&gt; 中添加&lt;h:outputText id="food" value="#viewBean.selectedFood" /&gt;

你会看到 outputText 总是Chicken

【讨论】:

我实际上也逐渐得出了这个结论。当delete 方法被调用时,我意识到selectedFood 为空。这是否意味着BalusC 说的是错误的? ohh noooo!!!!!!!!!!!!! 他没有错:P。我想你误解了他的话。他试图解释actionactionListener 的不同用法。 &lt;f:setPropertyActionListener&gt;actionListener 的一种,他提到它是为了在他的例子中展示你如何set an additional property。一般来说,actionListener 总是在action 之前被解雇。这就是为什么它总是与 action 一起使用。 他说要使用actionListener if you want have a hook before the real business action get executed。那么&lt;f:setPropertyActionListener&gt; 不是hook 在业务操作之前的delete?当我读到那句话时,我以为他的意思是&lt;f:setPropertyActionListener&gt;会在delete之前被执行 他在a hook before the real business action 中提到的动作是你的delete 方法,只有当它像这样声明action="#viewBean.delete"。如果你用actionListener 声明它,它就变成了一个不再是real business action 的监听器。

以上是关于JSF2:动作和动作监听器的主要内容,如果未能解决你的问题,请参考以下文章

h:commandLink 动作和 f:ajax 监听器的调用顺序

GUI编程-----事件监听

无法添加键盘事件监听器动作脚本

java在动作监听器中引用类

如何添加侦听多个按钮的动作侦听器

如何为多个 Jbutton 编写动作监听器