我在将大型数据集加载到 primefaces 树时遇到问题。
背景
我有一个大数据集,一个大的哈希图列表是具体的。我需要遍历列表的每个元素以在 PostConstruct 方法中构建树,以便显示素面。仅循环遍历列表大约需要 4 分钟。
我是如何处理这个问题的
所以,我想到了在多个线程之间划分循环(是的,这个上下文中的进程是可分割的)以提高性能。我创建线程,其中每个线程循环遍历树的一部分列表构建部分(每个线程每个循环一个树节点)。这使得处理时间缩短到大约一分钟。我想通过在启动时显示树的一部分(如 100 个节点)来进一步增强解决方案,然后让线程完成它们的工作,以保持页面对最终用户的响应。每个线程,在每个循环之后(即在创建树节点之后),都应该为 primefaces 触发某种事件(触发方法)以使用新创建的节点更新树。这就是我需要帮助的地方。
问题
我找不到以编程方式告诉 primefaces 更新树的方法。我了解到 RequestContext 用于此目的,但问题是从另一个线程调用它时它会失败。所以我想知道你是否有更好的方法来解决这个问题,或者告诉我我错过了什么。
简单的演示代码
xhtml 文件看起来像这样
<h:form id="form">
<h3 style="margin-top:0">Client</h3>
<p:tree value="#{treeBasicView.root}" var="node" id="clientTree">
<p:treeNode>
<h:outputText value="#{node}" />
</p:treeNode>
</p:tree>
</h:form>
托管 Bean 看起来像这样
@ManagedBean(name = "treeBasicView")
@ViewScoped
public class BasicView implements Serializable {
private static TreeNode root;
@PostConstruct
public void init() {
root = new DefaultTreeNode("Root", null);
TreeNode node0 = new DefaultTreeNode("Node 0", root);
TreeNode node1 = new DefaultTreeNode("Node 1", root);
TreeNode node00 = new DefaultTreeNode("Node 0.0", node0);
TreeNode node01 = new DefaultTreeNode("Node 0.1", node0);
TreeNode node10 = new DefaultTreeNode("Node 1.0", node1);
node1.getChildren().add(new DefaultTreeNode("Node 1.1"));
node00.getChildren().add(new DefaultTreeNode("Node 0.0.0"));
node00.getChildren().add(new DefaultTreeNode("Node 0.0.1"));
node01.getChildren().add(new DefaultTreeNode("Node 0.1.0"));
node10.getChildren().add(new DefaultTreeNode("Node 1.0.0"));
root.getChildren().add(new DefaultTreeNode("Node 2"));
BackgroundThread t1 = new BackgroundThread();
t1.index = 5;
t1.view = this;
t1.setName("BGT 1");
BackgroundThread t2 = new BackgroundThread();
t2.index = 15;
t2.view = this;
t2.setName("BGT 2");
t1.start();
t2.start();
}
public TreeNode getRoot() {
return root;
}
public synchronized void updateTree(TreeNode node) {
root.getChildren().add(node);
}
}
后台线程如下所示:
public class BackgroundThread extends Thread {
public int index;
public BasicView view;
@Override
public void run() {
int end = index + 10;
while (index < end) {
System.out.println(getName() + ": Node BG " + index);
view.updateTree(new DefaultTreeNode("Node BG: " + index));
index += 1;
try {
Thread.sleep(500);
} catch (InterruptedException ex) {
Logger.getLogger(BackgroundThread.class.getName()).log(Level.SEVERE, null, ex);
}
}
}
}
这在向树中添加新项目方面确实有效。但是我不能调用任何东西来以编程方式更新primefaces中的树。我的意思是,对象根(托管 bean 中的 TreeNode 类型)得到更新,但这并没有反映在 xhtml 页面中。
眼镜
我正在使用 JSF 2.2 和 primefaces 5.3。