0

我有一个 portlet,我在其中连接到数据库并显示一些数据。启用自动刷新后,我想从 db 加载数据,然后每 X 秒刷新一次页面(jsp)。

然而,虽然我确实了解计时器和任务是如何工作的,但我不太明白如何让它们在 portlet 中工作。

我尝试了两种不同的方法,但它们都没有像我预期的那样工作。这是第一个使用Thread.sleep(xxx); 功能

public void displayLog(final ActionRequest actionRequest,
            final ActionResponse actionResponse) throws IOException,
            PortletException {

        do {
            manager.setLastID(0);
            redirectToLog(actionRequest, actionResponse);

            try {
                Thread.sleep(3000);
            } catch (InterruptedException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        } while(manager.isAutoRefresh().equals("y"));
    }

这是重定向功能:

public void redirectToLog(ActionRequest actionRequest,
            ActionResponse actionResponse) throws IOException, PortletException {

        // load messages and display them
        manager.loadFromDB();

        // in case of error, redirect to error page
        if (manager.isConnError()) {
            actionResponse.setRenderParameter("jspPage",
                    "/html/visual/error.jsp");
            return;
        }

        // redirect
        actionRequest.setAttribute("messages", manager.getMessages());
        actionRequest.setAttribute("refresh", manager.isAutoRefresh());
        actionRequest.setAttribute("serviceFilter", manager.getServiceFilter());
        actionResponse
                .setRenderParameter("jspPage", "/html/visual/display.jsp");

    }

代码每 3 秒执行一次(如果我在那里放一些打印语句,我可以看到它调用了这个函数)。但是,我没有被重定向到 jsp 页面。相反,它只是“冻结”并永远执行此 while 循环。

我还尝试了使用计时器的第二种方法:

class LogDbTask extends TimerTask {
    private DbManager manager;
    private PortletVisual portlet;
    private ActionRequest actionRequest;
    private ActionResponse actionResponse;

    public LogDbTask(PortletVisual portlet, ActionRequest actionRequest, ActionResponse actionResponse) {
        this.portlet = portlet;
        this.actionRequest = actionRequest;
        this.actionResponse = actionResponse;
        manager = portlet.getManager(); 
    }


    public void run() {
        if (manager.isAutoRefresh().equals("y")) {
            try {
                manager.setLastID(0);
                portlet.redirectToLog(actionRequest, actionResponse);
            } catch (IOException e) {
                e.printStackTrace();
            } catch (PortletException e) {
                e.printStackTrace();
            }
        } else { 
            //Stop Timer.
            this.cancel();
        }
    }
}

我称之为使用

Timer timer = new Timer("LogDbTimer");
LogDbTask task = new LogDbTask(this, actionRequest, actionResponse);
timer.schedule(task, 0, 3000);

但问题仍然存在——我从来没有进入过 jsp 页面,尽管这个函数被反复调用。我不是 portelts 方面的专家,也不是多线程应用程序方面的专家。我究竟做错了什么?有没有一些简单的方法来解决这个问题?

很抱歉这个问题很累 - 我试着在里面放一些代码示例。如果不理解,我将尝试更正确地指定问题...

4

1 回答 1

1

Thread.sleep 方法一直“冻结”,因为 portlet 永远无法呈现视图。它位于循环中,从不真正返回要显示给用户的页面。

定时器任务方法的设计也存在缺陷。用户的浏览器必须对 portlet 代码进行页面请求,才能将任何内容发送回用户。这实质上意味着 TimerTask 可能会执行,但到它执行时,响应已经发送给用户,您无法再更新页面。

我建议将计时器逻辑移至客户端。您可以编写一些 JavaScript 来使用 AJAX 轮询 portlet,并使用那里的计时器来获取 resourceURL。您的 serveResource 方法可以只返回刷新的数据,然后在 JavaScript 中更新视图。这有助于防止整个页面刷新以减少服务器负载并使页面刷新更有效。

您唯一的其他选择是使用页面刷新 HTML 元标记或 JavaScript 计时器让浏览器在您希望页面更新时执行整个页面刷新。这降低了避免需要 AJAX 的复杂性,但我认为这是一个性能较差且不太优雅的解决方案。

于 2013-07-19T20:45:30.890 回答