Wicket - 会话间通信或手动创建新请求(循环)

时间:2013-06-29 12:02:40

标签: request wicket

我在不同会话的静态Hashmap中有一些wicket面板存储,我想做一些像某些面板通知地图,然后地图通知所有其他面板。 例如:

public class PanelMap{
    private static Map<Long, List<MyPanel>> map = new HashMap<Long, List<MyPanel>>();

public static void subscribe(Long id, MyPanel panel){
        if (!map.containsKey(id)){
            map.put(id, new ArrayList<MyPanel>());
        }
        map.get(id).add(panel);
    }
}

public static void notify(Long id, String notification){
        if (map.containsKey(id)){
            List<MyPanel> panels = map.get(id);
            for(MyPanel panel : panels){
                panel.newNotification(notification);
            }
        }
    }
}

在Panel中,newNotification(字符串通知)我想向服务器发送请求并在浏览器中刷新我的面板。

public void String newNotification(String notification){
   // do some business logic depends on notification
   onMyRequest();
}

我在wicket行为源文件中进行了一些搜索,我在AbstractDefaultAjaxBehavior找到了我试图在我的wicket面板中创建自己的onRequest方法,如下所示

private void onMyRequest(){
    AjaxRequestTarget target = ((WebApplication)getApplication()).newAjaxRequestTarget(getPage());
        target.add( _some_wicket_components_ );

        RequestCycle.get().scheduleRequestHandlerAfterCurrent(target);
    }

但我所做的只是Wicket Ajax Debug中的一些Ajax错误

 Wicket.Ajax.Call.processComponent: Component with id _containerdiv_ was not found while trying to perform markup update.
ERROR: Cannot find element with id: _someComponentIdOnPanel_

(这些组件存在)

我如何将自己的请求发送到服务器(或者如何获得有效的AjaxRequestTarget来更新我的组件?)

更新:我需要会话间通信。

2 个答案:

答案 0 :(得分:2)

要更新不同用户会话的面板,您显然无法使用当前的AjaxRequestTarget,因为这在某种程度上表示服务器与请求用户之间的单个通信,而另一个用户的浏览器无法知道。 (非常基本上说的)

您可以使用an AjaxSelfUpdatingTimerBehavior轮询更新。这将为每个用户定期生成新的AjaxRequestTarget,您可以使用它来附加更改的面板。这是一个非常基本和简单的实现,很可能会影响您的系统性能并产生相当多的流量。

另一种方法是使用类似Atmosphere的东西,它由Wicket-Atmosphere支持(快速启动可以找到here)并且在wicket-library.com有一些例子,但是这就是我所知道的。

答案 1 :(得分:1)

使用Wicket事件总线系统。了解&#34; Wicket活动基础设施&#34; free Wicket guide

的章节

首先,您需要创建一个类来封装通知和AjaxRequestTarget,并使用事件基础结构传递它们。

private class Notification {
    private String message;
    private AjaxRequestTarget target;

    ... constructor, getters, setters...
}

然后想要重新启动事件的面板必须覆盖onEvent方法,如下所示:

public void onEvent(IEvent<?> event) {
    if (event.getPayload() instanceof Notification) {
        Notification notification = (Notification) event.getPayload();

        ... do whatever you want before updating the panel ...

        // Update the panel 
        notification.getTarget().add(this);

    }
}

所有组件都会回放使用Wicket事件基础结构发送的所有事件。所以你可以使用像这样的方法从任何其他面板发送事件

protected void sendMessage(String message, AjaxRequestTarget target) {
    send(getSession(), Broadcast.BREADTH, new Notification(message, target));
}

请记住,如果您想使用AJAX更新组件,则需要设置setOutputMarkupId(true)。如果它是一个可以隐藏的组件,并且您希望使用AJAX使其可见,那么您需要设置setOutputMarkupPlaceholderTag(true)