Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/jsf/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
JSF2.2:viewAction触发器早于actionListener和action_Jsf_Jsf 2_Jsf 2.2 - Fatal编程技术网

JSF2.2:viewAction触发器早于actionListener和action

JSF2.2:viewAction触发器早于actionListener和action,jsf,jsf-2,jsf-2.2,Jsf,Jsf 2,Jsf 2.2,我一直在我的应用程序中使用preRenderView(+重定向和跳过回发攻击),我正试图用JSF2.2(MyFaces2.2.4)附带的viewAction来替换它。然而,我发现它比命令actionListener和action更早触发,这对我来说是毫无用处的。例如: import java.io.Serializable; import javax.faces.bean.ManagedBean; import javax.faces.bean.ViewScoped; @ManagedBea

我一直在我的应用程序中使用preRenderView(+重定向和跳过回发攻击),我正试图用JSF2.2(MyFaces2.2.4)附带的viewAction来替换它。然而,我发现它比命令actionListener和action更早触发,这对我来说是毫无用处的。例如:

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>

试验
#{testBean2.count}
因此addCount()System.out输出总是在渲染视图上的输出后面1,因为actionFunc()总是在addCount()之前触发

如果我想做一些事情,比如,如果(count==3)为重定向返回“newpage”,那么对于这样的决定来说,结果太早了。我可以在initView()中执行检查,也可以执行ConfigurableNavigationHandler.performNavigation(“newpage”),但我正试图用JSF2.2消除这种黑客行为

因此,如果我想让viewAction与我将要用action或actionListener更改的任何值一起工作,那么viewAction似乎毫无用处。它应该这样工作吗


谢谢

渲染响应阶段开始时的事件。但是,
viewAction
标记不允许该阶段。我假设在您的情况下,您应该在操作方法(
TestBean2#addCount
)中处理重定向,并忘记使用事件,因为对刚刚初始化的值执行检查毫无意义(这是您在第一次加载视图时使用
preRenderView
方法所做的)。在执行了逻辑之后,将其检查到动作方法中似乎是一种自然的方式

我相信事件也可以用来检查条件,但它们更多地与会话和应用程序状态有关,而不是与您当前的视图值有关。我的意思是,在呈现视图之前,如果您的店铺中没有可用的商品,您可以这样做来处理重定向:

public String checkItemsAvailable() {
    if (!dao.itemsAvailable()){
        return "noItemsAvailable";
    }
    return null;
}
但对于当前视图中正在评估的基于条件的重定向,在操作方法中执行重定向是最好的方法:

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


这个问题听起来很有趣,您是否阅读了关于
f:viewAction
标签的文章?还有其他属性,如
阶段
立即
,请尝试一下,如果您碰巧实现了,请不要忘记发布答案!你好已经试过了。默认情况下的阶段已经是最新的:“应用\u请求\u值、处理\u验证、更新\u模型\u值或调用\u应用程序。默认为调用\u应用程序。”immediate=“true”使其应用\u请求\u值,比现在更早。我开始写评论,但我最终以我认为有效的方式写下了一个完整的答案。希望对你有用。嗨。谢谢你的回答。在实际情况中,action方法实际上位于SessionScoped bean中,并更改其中的值(例如,模式a/B切换)并返回到同一视图(它总是返回null)。我的目的是让viewAction在每个页面中检查这一点,并相应地做一些事情(比如重定向)。因此,我不能在action方法中硬编码非null返回。就目前的情况而言,viewAction方法始终认为该值比preRenderView ses的值落后一步,preRenderView ses是正确的值。此外,进一步的测试显示,如果该操作转到其他视图,则viewAction在该操作后被触发。但是,如果操作返回到同一视图(即返回null;),则viewAction(同样,postback=true)会在操作之前触发。我不知道您的具体情况是什么,但是,看过viewAction文档后,我推断您可以使用它在当前请求之前设置的条件下重定向。如果您想根据当前请求重定向,请在当前按钮方法中使用重定向。不管怎样,您始终可以选择保持与使用prerenderview时相同的状态。@jplatium,如果您要使用的另一个视图也有一个
viewAction
标记,则您的第二条注释是有意义的。但这仅仅是因为这是您正在执行的另一个JSF循环(目标视图中的
viewAction
将在第一个视图的操作之后调用)。