Gwt 在Vaadin web app中将数据从一个用户推送到另一个用户

Gwt 在Vaadin web app中将数据从一个用户推送到另一个用户,gwt,vaadin,Gwt,Vaadin,我知道这可能需要10行以上的代码(希望不要超过50行),但我想知道你是否能帮我 我试图在运行时根据另一个用户的输入更新一个用户的UI线程。我创建了一个基本项目,它实现了三个预定义的用户(jim、tom和threeskin)。我想从jim发送一条消息给tom,并让它在tom的UI中显示为一个新的标签对象,而threeskin却不知道,即使他们都已登录。哦,吉姆不应该刷新他的页面。标签应该自动在屏幕上出现 如果说我希望得到一些帮助,那就太轻描淡写了 public class User {

我知道这可能需要10行以上的代码(希望不要超过50行),但我想知道你是否能帮我

我试图在运行时根据另一个用户的输入更新一个用户的UI线程。我创建了一个基本项目,它实现了三个预定义的用户(jim、tom和threeskin)。我想从jim发送一条消息给tom,并让它在tom的UI中显示为一个新的
标签
对象,而threeskin却不知道,即使他们都已登录。哦,吉姆不应该刷新他的页面。标签应该自动在屏幕上出现

如果说我希望得到一些帮助,那就太轻描淡写了

    public class User {
    public String nume;

    public User(String nume) {
        super();
        this.nume = nume;
      }
    }
    ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
    public class Engine implements ServletContextListener {
    public static ArrayList<User>userbase;
        public void contextDestroyed(ServletContextEvent arg0) { }
        public void contextInitialized(ServletContextEvent arg0) {
            System.out.println("This code is running at startup");
            userbase =new ArrayList<User>();
            userbase.add(new User("jim"));userbase.add(new User("tom"));userbase.add(new User("threeskin"));        
        }
    }
    ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
    public class InfigeUI extends UI {    
        User us3r;
        @WebServlet(value = "/*", asyncSupported = true)
        @VaadinServletConfiguration(productionMode = false, ui = InfigeUI.class)    
        public static class Servlet extends VaadinServlet {}    
            protected void init(VaadinRequest request) {
            VerticalLayout everything=new VerticalLayout();
            setContent(everything);
        if (us3r==null){everything.addComponent(auth());}else{everything.addComponent(main());}    
        }
        ComponentContainer auth(){    
            final VerticalLayout layout = new VerticalLayout();        
            layout.setMargin(true);
            TextField userField=new TextField();
            Button login = new Button("Log in");
            login.addClickListener(new Button.ClickListener() {
                public void buttonClick(ClickEvent event) {                
                    us3r=login(userField.getValue());
                    if (us3r!=null){
                    saveValue(InfigeUI.this, us3r);    
                    layout.removeAllComponents();
                   layout.addComponent(main());
                }else{Notification.show("I only know jim, tom and threeskin. Which one are you?");}}
            });
            layout.addComponent(userField);
            layout.addComponent(login);
            return layout;
        }    
        User login(String nume){
            for (int i=0;i<Engine.userbase.size();i++){
                if (nume.equals(Engine.userbase.get(i).nume)){return Engine.userbase.get(i);}                                
            }
            return null;
        }
    static void saveValue(InfigeUI ui,User value){
        ui.us3r=value;
        ui.getSession().setAttribute("something", value);
         VaadinService.getCurrentRequest().getWrappedSession().setAttribute("something", value);            
    }
    ComponentContainer main(){
        VerticalLayout vl=new VerticalLayout();
        Label label=new Label("This is the post-login screen");
        String name=new String(us3r.nume);
        Label eticheta=new Label(name);
        TextField to=new TextField("Send to");
        TextField message=new TextField("Message");
        Button sendNow=new Button("Send now!");
       vl.addComponent(eticheta);
        vl.addComponent(label);
        vl.addComponent(eticheta);
        vl.addComponent(to);
        vl.addComponent(message);
        vl.addComponent(sendNow);
        return vl ;
        }
    }
公共类用户{
公共字符串nume;
公共用户(字符串nume){
超级();
this.nume=nume;
}
}
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
公共类引擎实现ServletContextListener{
公共静态阵列服务器;
public void contextdestromed(ServletContextEvent arg0){}
公共void contextInitialized(ServletContextEvent arg0){
System.out.println(“此代码在启动时运行”);
userbase=newarraylist();
userbase.add(新用户(“jim”);userbase.add(新用户(“tom”);userbase.add(新用户(“threeskin”));
}
}
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
公共类InfigeUI扩展UI{
用户us3r;
@WebServlet(value=“/*”,asyncSupported=true)
@VaadinServletConfiguration(productionMode=false,ui=InfigeUI.class)
公共静态类Servlet扩展了VaadinServlet{}
受保护的void init(VaadinRequest请求){
VerticalLayout everything=新建VerticalLayout();
内容(一切);
if(us3r==null){earthing.addComponent(auth());}else{earthing.addComponent(main());}
}
ComponentContainer auth(){
最终垂直布局=新建垂直布局();
布局。设置页边距(真);
TextField userField=新建TextField();
按钮登录=新按钮(“登录”);
login.addClickListener(新建按钮.ClickListener(){
公共无效按钮单击(单击事件){
us3r=login(userField.getValue());
如果(us3r!=null){
saveValue(InfigeUI.this,us3r);
layout.removeAllComponents();
layout.addComponent(main());
}else{Notification.show(“我只认识吉姆、汤姆和三个皮肤。你是哪一个?”);}
});
layout.addComponent(用户字段);
layout.addComponent(登录);
返回布局;
}    
用户登录(字符串nume){

对于(inti=0;i基本上你想要三样东西

  • 用户的UI更新本身不执行任何操作,或者换句话说,从服务器发送到浏览器的消息。要启用此功能,您需要使用@Push对UI类进行注释。否则,只有当用户执行导致服务器访问的操作(例如,单击按钮)时,才会显示更新

  • 在UI实例之间发送消息的某种方式(每个用户有一个UI实例)。您可以为此使用一些消息总线实现(CDI、Spring等),或者您可以简单介绍如何使用静态字段(静态字段在所有用户之间共享)。请参阅,例如,了解一种方法。在此处避免使用所有*.getCurrent方法也是一个好主意,因为在许多情况下,这些方法会引用超出您想象的另一个UI(例如,当您处于接收方代码中时为sender),并且您会执行超出您预期的操作

  • 当消息到达时,安全地更新UI。这是使用UI.access完成的,在聊天示例中也可见


  • 首先,您需要在项目上启用服务器推送 基于Vaadin文档。 但是,下面的代码示例将给出您想要的:

  • 创建广播侦听器接口:

    公共接口广播侦听器{ 公共无效接收广播(最终字符串消息); }

  • 广播员级别:

    公营广播公司{

    private static final List<BroadcastListener> listeners = new CopyOnWriteArrayList<BroadcastListener>();
    
    public static void register(BroadcastListener listener) {
        listeners.add(listener);
    }
    
    public static void unregister(BroadcastListener listener) {
        listeners.remove(listener);
    }
    
    public static void broadcast(final String message) {
        for (BroadcastListener listener : listeners) {
            listener.receiveBroadcast(message);
        }
    }
    

  • 您可以找到完整链接。

    谢谢,Artur!通过聊天应用查看示例。稍后可能会发布结果。如果成功,您将非常棒。我将在大约两周内尝试实现它,我将获得一些反馈。谢谢!我已经使用此解决方案实现了一个消息中心,因此用户可以在他们之间交换消息,而不是使用live noti这里有一些问题。我不明白的是:如何以及在何处指定要接收广播的用户?据我所知,这会向所有连接的客户端发送消息。我想针对一个特定的用户。帮助?您可以使用自己类中的消息类型并包括发送者(和接收者)在上面提到的示例中,消息是简单的字符串类型。
    @Override
    protected void init(VaadinRequest request) {
        final VerticalLayout layout = new VerticalLayout();
        layout.setMargin(true);
        setContent(layout);
    
        final TextArea message = new TextArea("",
                "The system is going down for maintenance in 10 minutes");
        layout.addComponent(message);
    
        final Button button = new Button("Broadcast");
        layout.addComponent(button);
        button.addClickListener(new Button.ClickListener() {
            @Override
            public void buttonClick(ClickEvent event) {
                Broadcaster.broadcast(message.getValue());
            }
        });
    
        // Register broadcast listener
        Broadcaster.register(this);
    }
    
    @Override
    public void detach() {
        Broadcaster.unregister(this);
        super.detach();
    }
    
    @Override
    public void receiveBroadcast(final String message) {
        access(new Runnable() {
            @Override
            public void run() {
                Notification n = new Notification("Message received",
                        message, Type.TRAY_NOTIFICATION);
                n.show(getPage());
            }
        });
    }