0

请阅读到最后,有很多编辑
我有这段 JSF 代码:

<h:form>
    <h:dataTable class="table-striped" var="_product"
        value="#{productManager.products}"
        border="1"
        binding="#{productManager.table}">
        <h:column>
            <f:facet name="header">Product</f:facet>
            #{_product.name}
        </h:column>
        <h:column>
            <f:facet name="header">Available Units</f:facet>
            #{_product.stock}
        </h:column>
        <h:column>
            <f:facet name="header">Category</f:facet>
            #{_product.category}
        </h:column>
        <h:column>
            <f:facet name="header">Price</f:facet>
            #{_product.price}
        </h:column>
        <h:column>
            <f:facet name="header">Description</f:facet>
            #{_product.description}
        </h:column>
        <h:column>
            <f:facet name="header">Select</f:facet>
            <h:commandButton class="btn btn-primary" value="Select"
                action="#{productManager.selectProduct}"/>
        </h:column>
    </h:dataTable>
</h:form>
<h:form>
    <h:outputLabel for="productName">Selected Product: </h:outputLabel>
    <h:inputText value="#{productManager.selectedDesiredCategory}"/>
    <h:commandButton value="Filter category" action="#{productManager.filterProductsByCategory}"/>
    <h:outputText id="productName" value="#{productManager.selectedName}"/><br/>
    <h:outputLabel for="units">Units: </h:outputLabel>
    <h:inputText id="units" value="#{productManager.selectedUnits}"/>
    <h:commandButton value="Add to basket" action="#{productManager.addToBasket(accountManager.username)}"/><br/>
    <h:outputText rendered="#{productManager.availableMessages}"
        value="#{productManager.message}"/>
</h:form>

#{productManager.filterProductsByCategory}命令按钮重定向到这个 java 方法:

public void filterProductsByCategory() {
    this.products = controller.obtainProductListByCategory(selectedDesiredCategory);
    showMessage("Filtered by selected category");
} 

在这里,我products使用按类别过滤的新产品集更新列表的内容,以在视图中显示它们。问题是页面没有重新加载以显示新内容。这是如何实现的?

编辑: showMessage 方法实际上是在视图中显示,所以页面正在重新加载,但由于某种原因,表没有更新。也许这是查询返回的数据有问题,我实际上正在研究。

编辑:查询返回了良好的结果,正如我的调试过程所证实的那样,但网页没有正确地重新加载表中的数据。

编辑:我发现了一些非常奇怪的东西。这是 JSF 页面引用的代码:

public void filterProductsByCategory()
   {
      filtered = true;
      products = controller.obtainProductListByCategory(selectedDesiredCategory);
      showMessage("Filtered by selected category");
   } 

我现在使用布尔值来实际知道何时必须提供过滤列表(请参阅下面的代码中的原因)这是getter列表products

   public List<Product> getProducts()
   {
      if(filtered)
      {
          filtered = false;
          return products;
      }
      products = controller.obtainProductList();
      return products;
   }

如果这是真的,它应该只发送实际的过滤products变量。但由于某种原因,它在方法内一次又一次地循环(即使在returnif 内的语句之后),并再次将所有产品发送到视图。为什么会发生这种情况?

4

1 回答 1

3

默认情况下,JSF 调用 getter 方法的次数与视图中使用的次数一样多。例如,对于您的List<Product> products字段及其各自的 getter,如果在您的视图中#{productManager.products出现两次,即在 Facelets 代码中,那么 getter 也将被执行两次。出于这个原因,托管 bean 中的 getter 和 setter 方法应该尽可能干净,并且不应该包含任何涉及的业务逻辑。

基本上,您应该在创建托管 bean 之后和视图呈现时间之前从数据库中检索一次产品列表。为此,您可以使用@PostConstruct注解来装饰void将在创建 bean 后执行的方法。

在代码中:

@ManagedBean
@ViewScoped
public class ProductManager {
    private List<Product> products;
    @PostConstruct
    public void init() { //you can change the method name
        //if you manually handle the controller, initialize it here
        //otherwise, let it be injected by EJB, Spring, CDI
        //or whichever framework you're working with
        products = controller.obtainProductList();
    }
    public List<Product> getProducts() {
        //plain getter, as simple as this
        //no business logic AT ALL
        return this.products;
    }
    public void filterProductsByCategory() {
        filtered = true;
        products = controller.obtainProductListByCategory(selectedDesiredCategory);
        //I guess this method logs a message or something...
        showMessage("Filtered by selected category");
    }
}

更多信息

于 2013-10-17T00:57:55.253 回答