我正在开发一个 JSF + Primefaces Web 应用程序,其中我需要每 20 秒向服务器发出一个 RESTful GET 请求,并显示返回的数据。这目前有效,但“每 10 秒”部分除外。我可以单击命令按钮来检索和显示数据。我试图用 ScheduledExecutorService 来实现 repitition。现在,当我单击 commandButton 时,支持函数每 10 秒运行一次(我可以通过 System.out.println 输出看到这一点),但是在再次单击该按钮之前,表格不会更新以显示数据。下面是我的代码:
HTML(嵌入在表单中)
<p:commandButton id="andon_layout--board0--loadboard0"
value="Load board"
actionListener="#{decryptionBean.loadBoardListen0}"
update="dataPanelGrid" />
<div id="andon_layout--board0--display_div"
class="ui-datatable ui-widget ">
<h:panelGrid id="dataPanelGrid"
columns="#{decryptionBean.displayBoardArray[0].datatableNumberOfCols}"
headerClass="ui-datatable ui-widget-header ">
<f:facet name="header">
<h:outputText
value="#{decryptionBean.displayBoardArray[0].locationName}" />
</f:facet>
<c:forEach var="row"
items="#{decryptionBean.displayBoardArray[0].displayData}">
<c:forEach var="value" items="#{row}">
<div class="ui-dt-c">#{value}</div>
</c:forEach>
</c:forEach>
</h:panelGrid>
</div>
JAVA
@ManagedBean
@ViewScoped
public class DecryptionBean implements Serializable {
...
private Updater left = new Updater(0);
public void loadBoardListen0(ActionEvent event){
left.stopBoardLoading();
left.beginBoardLoading();
}
public final class Updater {
@PreDestroy
public void destroy() {
fScheduler.shutdownNow();
}
private ScheduledExecutorService fScheduler;
//
private long fDelayBetweenRuns = 10;
int boardNumber;
/**
* If invocations might overlap, you can specify more than a single
* thread.
*/
private int NUM_THREADS = 1;
public int isRunning = 0;
private boolean DONT_INTERRUPT_IF_RUNNING = false;
private ScheduledFuture<?> loadBoardFuture;
private class BoardLoaderTask implements Runnable {
private int boardNumber;
public BoardLoaderTask(int boardNumber) {
this.boardNumber = boardNumber;
}
public void run() {
DecryptionBean.this.loadBoard(boardNumber);
}
}
public Updater(int boardNumber){
this.boardNumber = boardNumber;
fScheduler = Executors.newScheduledThreadPool(NUM_THREADS);
}
void beginBoardLoading(){
if(isRunning == 1){
this.stopBoardLoading();
}
isRunning = 1;
Runnable boardLoaderTask = new BoardLoaderTask(this.boardNumber);
loadBoardFuture = fScheduler.scheduleWithFixedDelay(boardLoaderTask,
0, fDelayBetweenRuns, TimeUnit.SECONDS);
}
void stopBoardLoading(){
if(isRunning == 1){
isRunning = 0;
Runnable stopBoard = new StopLoadingTask(loadBoardFuture);
fScheduler.schedule(stopBoard, 0, TimeUnit.SECONDS);
}
isRunning = 0;
}
private class StopLoadingTask implements Runnable {
StopLoadingTask(ScheduledFuture<?> aSchedFuture) {
fSchedFuture = aSchedFuture;
}
private ScheduledFuture<?> fSchedFuture;
@Override
public void run() {
// TODO Auto-generated method stub
fSchedFuture.cancel(DONT_INTERRUPT_IF_RUNNING);
}
}
}
loadBoard(int boardNum) 是一个很大的函数,所以我没有在这里发布,但是如果你们认为有必要,我会发布。
在我看来,问题出在p:commandbutton update
属性上:似乎 dataPanelGrid 是在开始时更新的loadBoardListen0
,而不是结束时。需要明确的是:支持功能在第一次单击时运行,但仅在第二次、第三次、第四次等时更新 GUI。单击有关此的任何指导?提前致谢!
编辑 1:
我现在正在尝试使用 PrimePush 和套接字来执行此操作,但我也遇到了麻烦。我将此添加到我的代码中:HTML
<p:socket onMessage="handleMessage" channel="/IPVS" autoConnect="false"/>
...
function handleMessage(data) {
console.log("data received: " + data);
var elm = "andon_layout--board" + data + "--display_div";
elm.style.display="none";
var redrawFix = elm.offsetHeight;
elm.style.display="block";
}
JAVA(在 loadBoard(int) 的末尾)
System.out.println("Loading data... no exceptions thrown");
System.out.println("context created");
PushContextFactory.getDefault().getPushContext().push("/IPVS", Integer.toString(displayBoardNum));
System.out.println("Just pushed to /IPVS");
每当我尝试运行代码时,它都会在 PushContextFactory 行停止。我得到的输出如下:
Loading data... no exceptions thrown
context created
而且根本没有。这也可以防止循环运行。请注意,我仍在使用 ScheduledExecutorService,并且只是尝试在每次任务完成时推送一些数据。有任何想法吗?