h:commandButton在加载页面时不使用JSFbean

h:commandButton在加载页面时不使用JSFbean,jsf,jsf-2,view-scope,Jsf,Jsf 2,View Scope,问题:h:CommandButtonAjax在加载页面时不能与JSFbean一起工作 具有长列表的have JSF页面(加载需要几秒钟): #{实体} 和托管视图范围bean“MyViewBean”: package mypackage; import java.util.ArrayList; import java.util.List; import javax.inject.Named; import org.springframework.context.annotation.Sco

问题:h:CommandButtonAjax在加载页面时不能与JSFbean一起工作

具有长列表的have JSF页面(加载需要几秒钟):


#{实体}
和托管视图范围bean“MyViewBean”:

package mypackage;

import java.util.ArrayList;
import java.util.List;
import javax.inject.Named;
import org.springframework.context.annotation.Scope;

@Named
@Scope(value = "view")
public class MyViewBean {

    private static int beanNrCounter = 0;
    private static final List<String> bigList = new ArrayList();
    static {
        for (int i = 0; i < 100000; i++) {
            bigList.add("Item in big list " + i);
        }
    }

    private final String name;

    public MyViewBean() {
        beanNrCounter++;
        name = "BEAN NR " + beanNrCounter;
        System.out.println("Created MyViewBean with name " + name);  
    }

    public String actRedirectToAnotherView() {
        String viewName = "anotherView.jsf";//actually some complex operation which decides where to redirect user 
        System.out.println("Redirecting to another view " + viewName );
        return viewName + "&faces-redirect=true";
    }

    public String getName() {
        return name;
    }

    public List<String> getBigList() {
        return bigList;
    }

}
package-mypackage;
导入java.util.ArrayList;
导入java.util.List;
导入javax.inject.Named;
导入org.springframework.context.annotation.Scope;
@命名
@范围(value=“视图”)
公共类MyViewBean{
专用静态int-beanNrCounter=0;
private static final List bigList=new ArrayList();
静止的{
对于(int i=0;i<100000;i++){
bigList.add(“大列表中的项目”+i);
}
}
私有最终字符串名;
公共MyViewBean(){
beanNrCounter++;
name=“BEAN NR”+beanNrCounter;
System.out.println(“创建了名为“+name”的MyViewBean);
}
公共字符串actRedirectToAnotherView(){
String viewName=“anotherView.jsf”;//实际上是一个复杂的操作,决定将用户重定向到何处
System.out.println(“重定向到另一个视图”+视图名);
返回viewName+“&faces redirect=true”;
}
公共字符串getName(){
返回名称;
}
公共列表getBigList(){
返回大列表;
}
}
如果在页面加载时单击按钮“重定向”,则不会执行方法“actRedirectToAnotherView”,而是创建另一个“MyViewBean”bean。若我点击按钮,那个么页面已加载,一切正常

我已经检查过,如果页面加载,则单击“重定向”按钮。参数javax.faces.ViewState通过ajax post传递,但如果页面加载,则缺少-javax.faces.ViewState(因此创建了新视图)

若我将托管bean的作用域更改为“请求”,问题仍然存在(“重定向”按钮仍然不工作,actRedirectToAnotherView未执行)

如何在页面加载时修复ajax行为? 在我看来,只要访问MyViewBean,客户端就知道javax.faces.ViewState,所以不管页面是否已经加载,都应该传递javax.faces.ViewState

我正在使用:

  • JSF Mojarra(2.2.6)
  • Spring:“查看范围”是通过示例完成的
  • 基本面(5.1)

看看这个例子,我希望你觉得它有用

Facelets:

<h:form>
    <h:commandLink value="show" action="#{showProducts.toggleShow}">
        <f:ajax render="products"/>
    </h:commandLink>
    <h:panelGroup id="products">
        <h:dataTable var="product" value="#{showProducts.products}" rendered="#{!showProducts.show}">
            <h:column>#{product.name}</h:column>
        </h:dataTable>
    </h:panelGroup>
</h:form>

#{product.name}
对于托管Bean

private List<Product> products;

@PostConstruct
public void init() {
    products = this.getProductManager().getProducts();
}

public List<Product> getProducts() {
    return products;
}
Or if it actually needs to be lazily loaded, then rather do so:

private List<Product> products;

public List<Product> getProducts() {
    if (products == null) {
        products = this.getProductManager().getProducts();
    }
    return products;
}
私有列表产品;
@施工后
公共void init(){
products=this.getProductManager().getProducts();
}
公共列表产品(){
退货产品;
}
或者,如果它确实需要延迟加载,那么应该这样做:
私人上市产品;
公共列表产品(){
如果(产品==null){
products=this.getProductManager().getProducts();
}
退货产品;
}

我不确定它对我的情况有什么帮助(我是,在getter中没有做任何昂贵的操作,我的列表是静态的,在应用程序启动时只加载一次)。问题在于javax.faces.ViewState在页面加载时未被传递(页面大小约为7Mb,因此通常需要几秒钟)最安全的方法是在加载页面时阻止页面或延迟加载页面内容的一部分(=与惰性数据表不同的内容)可能Kukeltje两种建议的解决方案都能奏效。只是阻塞并不是最用户友好的解决方案,延迟加载只会使问题变得不那么明显(对于真正缓慢的互联网连接,它仍然存在)。对我来说,看起来很奇怪,当页面加载时,几乎所有基于jsf ajax的功能都不能像预期的那样工作(很容易被缓慢的互联网连接所察觉),除了具体的问题之外,为什么要使用POST进行导航?使用
。这只是用最少的代码来显示问题的原型。actRedirectToAnotherView方法执行一些“业务逻辑”,并“决定”将用户重定向到哪里。我将更新代码示例,使其“符合逻辑”。好的。它真的必须和桌子的形状一样吗?表中似乎没有任何与请求相关的输入。否则,只需将按钮设置为其自身的形式。你知道,每张表格一张。
private List<Product> products;

@PostConstruct
public void init() {
    products = this.getProductManager().getProducts();
}

public List<Product> getProducts() {
    return products;
}
Or if it actually needs to be lazily loaded, then rather do so:

private List<Product> products;

public List<Product> getProducts() {
    if (products == null) {
        products = this.getProductManager().getProducts();
    }
    return products;
}