Wicket调用冗长的操作并通过ajax进行更新

基于这个SO问题 ,我已经了解到Wicket将后续的AJAX请求排队。 现在我的页面上有几个AJAX请求,我想再添加一个产生冗长操作的页面。

public void populateItem(final Item item) { final MyObject object = (MyObject) item.getModelObject(); // ... a couple of fields Label statusLabel = new Label("status", new AbstractReadOnlyModel() { @Override public Object getObject() { return someService.doSomeLengthyOperation(); } }); statusLabel.add(new AjaxSelfUpdatingTimerBehavior(Duration.seconds(5))); item.add(statusLabel) } 

一旦这个Ajax请求触发,它可能需要一分钟才能完成执行。 这里的问题是someService.doSomeLengthyOperation()将执行n times the number of rows我拥有n times the number of rows ,这意味着我将排队n times two-minutes 。 现在,正如我所提到的,Wicket排队后续的AJAX请求。

会发生什么呢?它需要我number-of-rows * minutes-it-take-to-finish-the-operation来加载页面或做其他需要AJAX的东西

 new AjaxButton("ajax-button"){ @Override protected void onSubmit(AjaxRequestTarget target, Form form) { //.. this won't be executed until all the statusLabels have finished invoking getObject() } } 

我想避免创建一个公开我的服务的Web服务,并且必须编写自己的AJAX调用。 我有什么选择? (使用Wicket 1.5 / Pax-Wicket)

最简单的方法是让初始Ajax请求快速返回(没有任何结果),并将AjaxSelfUpdatingTimerBehavior添加到目标组件。 如果有结果,此行为将检查间隔(例如每10秒左右)。 如果有结果,它应该更新组件并删除它自己。

这样,您可以在单独的任务中执行操作,而不会阻止Ajax调用。

为了详细说明,我创建了一个可运行的快速入门 ,它可以像你所描述的那样发出5个Ajax调用,每个调用在10秒到1分钟之间运行一段随机时间。 同时,还有一个带计数器的响应式AjaxLink。

主要思想是将实际的Ajax调用与对slow方法的调用分开。

 add(new ListView("list", list) { @Override protected void populateItem(ListItem item) { DataHolder dh = item.getModelObject(); item.add(new Label("itemNumber", new PropertyModel(dh, "number"))); Label result = new Label("itemResult", new PropertyModel(dh, "result")); result.setOutputMarkupId(true); result.add(new AjaxSelfUpdatingTimerBehavior(Duration.seconds(2))); item.add(result); Thread thread = new Thread(new Processor(item.getModelObject())); thread.start(); } }); 

如您所见,标签模型不再直接调用doSomeLengthyOperation() 。 而是产生一个新的线程来完成繁重的工作。 Processor类只是实现Runnable接口并使用run-method来完成工作(在你的情况下,在演示中它只是等待一段时间)。

PropertyModel的getter封装了这个特技并使其透明,同时快速返回以防止阻塞。

 public String getResult() { String retValue; if (!processed) { retValue = String.format("Still busy after %d requests", counter++); } else { retValue = result; } return retValue; } 

处理过的成员只是一个标志,处理器用它来表示它已经完成等待(ehr工作)。

由于您可能会同时发出超过5个线程,我建议使用某种Threadpool,但这超出了这个小型演示的范围。


免责声明:这不是生产代码。 它只是用于演示。 它对你的资源不好,也不会优雅地处理它的缺乏。 当用户点击重新加载或其他任何事情时,它将无法工作。

我不完全确定WicketStuff异步任务是否可以帮助你,但尝试一下:

https://github.com/wicketstuff/core/wiki/Async-tasks

以下是Async Tasks项目中的简短演示:

 public class DemoPage extends WebPage implements IRunnableFactory { public DemoPage() { Form form = new Form("form"); AbstractTaskContainer taskContainer = DefaultTaskManager.getInstance() .makeContainer(1000L, TimeUnit.MINUTES); ProgressButton progressButton = new ProgressButton("button", form, Model.of(taskContainer), this, Duration.milliseconds(500L)); ProgressBar progressBar = new ProgressBar("bar", progressButton); add(form); form.add(progressButton); form.add(progressBar); } @Override public Runnable getRunnable() { return new IProgressObservableRunnable() { // Runnable implementation. }; }