我有一个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的专家,也不是多线程应用程序的专家。我究竟做错了什么?有没有简单的方法来解决这个问题?
很抱歉让人筋疲力尽 - 我试着在那里放一些代码示例。如果不理解,我会尝试更恰当地指定问题...
答案 0 :(得分:1)
Thread.sleep方法保持“冻结”,因为portlet永远不会呈现视图。它位于循环中,从不实际返回要显示给用户的页面。
计时器任务方法在设计上也存在缺陷。用户的浏览器必须对portlet代码发出页面请求,以便将任何内容发送回用户。这实际上意味着TimerTask可能会执行,但到时它已经发送给用户,您无法再更新页面。
我建议将定时器逻辑移到客户端。您可以使用AJAX编写一些JavaScript来轮询portlet,使用计时器编写一个resourceURL。您的serveResource方法可以返回刷新的数据,然后在JavaScript中更新视图。这有助于防止整页刷新以减少服务器负载并使页面更有效地刷新。
您唯一的另一个选择是使用页面刷新HTML元标记或JavaScript计时器,让浏览器在您希望页面更新时进行整页刷新。这降低了避免使用AJAX的复杂性,但我认为这是一种性能较差且不太优雅的解决方案。