JSF 2.2:viewAction触发器早于actionListener和action

时间:2014-07-07 20:09:47

标签: jsf jsf-2 jsf-2.2

我一直在我的应用中使用preRenderView(+重定向和跳过回发黑客),我试图用JSF2.2(MyFaces 2.2.4)附带的viewAction替换它。但是我发现它比命令actionListener和动作更早触发它对我的目的来说相当无用。例如:

import java.io.Serializable;

import javax.faces.bean.ManagedBean;
import javax.faces.bean.ViewScoped;

@ManagedBean
@ViewScoped
public class TestBean2 implements Serializable {

  int count = 0;

  public void actionFunc() {
    System.out.println(count);
  }

  public String addCount() {
    count++;
    return null;
  }

  public int getCount() {
    return count;
  }

  public void initView() {
    System.out.println("initView");
  }

  public void setCount(int count) {
    this.count = count;
  }

}

然后是一个非常简单的.xhtml:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" 
    "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<html xmlns="http://www.w3.org/1999/xhtml" xmlns:ui="http://java.sun.com/jsf/facelets" xmlns:h="http://java.sun.com/jsf/html"
  xmlns:f="http://java.sun.com/jsf/core" xmlns:pt="http://xmlns.jcp.org/jsf/passthrough" xmlns:jsf="http://xmlns.jcp.org/jsf"
  xmlns:t="http://myfaces.apache.org/tomahawk" xmlns:p="http://primefaces.org/ui">

<f:metadata>
  <f:event type="preRenderView" listener="#{testBean2.initView}" />
  <f:viewAction action="#{testBean2.actionFunc}" onPostback="true" />
</f:metadata>

<ui:composition template="/WEB-INF/template.xhtml">
  <ui:define name="title">Test</ui:define>

  <ui:define name="content">
    #{testBean2.count}
        <h:form>
      <h:commandButton styleClass="btn btn-primary" action="#{testBean2.addCount}" value="addCount">
      </h:commandButton>
    </h:form>
  </ui:define>
</ui:composition>
</html>

因此,addCount()System.out输出总是落后于渲染视图上的1,因为actionFunc()总是在addCount()之前触发。

如果我想做类似的事情,if(count == 3)做一个返回&#34; newpage&#34;对于重定向,它对于这样的决定来说太早了。我可以在initView()中进行检查并执行ConfigurableNavigationHandler.performNavigation(&#34; newpage&#34;),但这是我试图用JSF 2.2消除的那种黑客攻击。

因此,如果我希望它能够处理我将使用action或actionListener进行更改的任何值,那么viewAction似乎毫无用处。它应该像这样工作吗?

谢谢!

1 个答案:

答案 0 :(得分:1)

RENDER_RESPONSE 阶段开头的

preRenderView事件is executed。但是,viewAction标记不允许该阶段。我想在你的情况下,你应该在你的动作方法(TestBean2#addCount)中处理重定向而忘记使用事件,因为对于刚刚初始化的值执行检查是没有意义的(&# 39;当您第一次加载视图时,使用preRenderView方法执行的操作)。在执行了你的逻辑后,将它检入动作方法,似乎是它的自然方式。

我相信事件也可用于检查条件,但它们更多地与会话和应用程序状态有关,而与您当前的视图值无关。我的意思是,在您的视图呈现之前,当您的商店中没有可用的商品时,您可以执行此操作来处理重定向:

public String checkItemsAvailable() {
    if (!dao.itemsAvailable()){
        return "noItemsAvailable";
    }
    return null;
}

但是对于基于在当前视图中评估的条件的重定向,在动作方法中执行它是最好的方法:

public void addCount() {
    count++;
    if (count>3){
        FacesContext.getCurrentInstance()
            .getExternalContext().redirect("index.xhtml");
    }
}

另见: