在portlet中安排任务

时间:2013-07-19 07:46:55

标签: java jsp timer portlet

我有一个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页面。相反,它只是“冻结”并在永远循环时执行此操作。

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

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的专家,也不是多线程应用程序的专家。我究竟做错了什么?有没有简单的方法来解决这个问题?

很抱歉让人筋疲力尽 - 我试着在那里放一些代码示例。如果不理解,我会尝试更恰当地指定问题...

1 个答案:

答案 0 :(得分:1)

Thread.sleep方法保持“冻结”,因为portlet永远不会呈现视图。它位于循环中,从不实际返回要显示给用户的页面。

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

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

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