JSF2.2:viewAction触发器早于actionListener和action
我一直在我的应用程序中使用preRenderView(+重定向和跳过回发攻击),我正试图用JSF2.2(MyFaces2.2.4)附带的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
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
将在第一个视图的操作之后调用)。