0

我正在开发一个 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,并且只是尝试在每次任务完成时推送一些数据。有任何想法吗?

4

1 回答 1

2

您应该尝试使用 Primefaces投票标签。这将每 x 秒触发一个 ajax 事件。您可以使用它在您的支持 bean 上调用您的“getData”方法。这会将轮询的逻辑移动到您的 JSF 页面,而不是支持 bean。

例如:

<p:poll interval="10" listener="#{decryptionBean.getData}" update="dataPanelGrid" />

这要求您在支持 bean 中有一个简单的“getData”方法,而不需要调度代码。

于 2013-08-08T14:50:10.857 回答