【问题标题】:Vaadin web application on tomcat creates only one instance of webapp for all usersTomcat 上的 Vaadin Web 应用程序只为所有用户创建一个 webapp 实例
【发布时间】:2012-08-23 18:22:19
【问题描述】:

我的英语有些问题,所以我为错误道歉。

我是 Java 编程的初学者。我使用 IntelliJIdea 作为 IDE,使用 Vaadin 框架创建 GUI,使用 tomcat 作为 Web 服务器。项目是用 maven 生成的。 为了创建应用程序,我使用以下来源作为示例:

From stack overflow

Video tutorial

有Application类,(不是com.vaadin.Application继承者),而是单例。

package com.exadel.dinnerorders.vaadinwindow.application;
import com.exadel.dinnerorders.entity.Order;
import com.exadel.dinnerorders.entity.User;
import com.exadel.dinnerorders.service.TasksManagerService;
import com.google.common.eventbus.EventBus;

public class Application {
    private EventBus eventBus = new EventBus();
    private static Application INSTANCE = new Application();
    private User user;
    private Order order;
    private TasksManagerService tasksManagerService = new TasksManagerService();

    private Application() {
        tasksManagerService.start();
    }

    public synchronized static Application getInstance(){
        return INSTANCE;
    }

    public EventBus getEventBus() {
        return eventBus;
    }

    public void setUser(User user) {
        this.user = user;
    }

    public User getUser() {
        return user;
    }

    public Order getOrder() {
        return order;
    }

    public void setOrder(Order order) {
        this.order = order;
    }

    public TasksManagerService getTasksManagerService() {
        return tasksManagerService;
    }
}

还有WebApplicationController 类,它扩展了com.vaadin.Application

package com.exadel.dinnerorders.vaadinwindow.application;

import com.google.common.eventbus.EventBus;
import com.google.common.eventbus.Subscribe;
import com.vaadin.terminal.Sizeable;
import com.vaadin.ui.*;

import java.util.Collection;

public class WebApplicationController extends com.vaadin.Application {
    private EventBus eventBus = Application.getInstance().getEventBus();
    private Layout loginLayout;
    private String datePattern = "YYYY-MM-DD";

    @Override
    public void init() {
        createLayouts();
        createMainWindow();
        eventBus.register(this);
        setTheme("apptheme");
    }
    //some another methods for initialization main window and layouts
}

所以,看来我的应用程序运行良好。但我面临下一个问题: 我在 Tomcat 7 配置的想法中运行应用程序。它启动没有任何问题。我将 Opera 作为浏览器打开并以 user1 等身份登录。一切似乎都正常。然后我打开 Google Chrome 或其他浏览器并以 user2 身份登录。如果在 Opera 中刷新窗口,它会显示知道 user2 已登录,但不是 user1。我曾尝试在不同的计算机上做同样的事情,我得到了相同的结果。 (在一台机器上登录为 user1,在另一台机器上登录为 user2)。 Firebug显示sessionID在不同浏览器中是不同的。

似乎问题出在我配置 servlet 的 web.xml 文件中。但是我尝试了不同的配置示例,并且总是得到相同的结果。

很遗憾,我没能在谷歌或其他论坛上找到答案。

【问题讨论】:

    标签: java vaadin


    【解决方案1】:

    我会说您的问题与静态应用程序单例有关。静态数据在 JVM 内的所有用户之间共享。

    【讨论】:

      【解决方案2】:

      正如 Henri 指出的,您在这里使用的是静态应用程序单例。这意味着每次调用 Application#getInstance()(以及扩展为 WebApplicationController#getInstance)都将返回相同的应用程序实例,无论调用来自哪个 HTTP 会话。

      如果您需要从 Web 应用程序的其他部分轻松访问应用程序实例,最常用的方法是使用 ThreadLocal<Application> 变量来存储实例。通过使用HttpServletRequestListener,您可以在请求开始时设置该值,并在请求结束时清除它。

      示例代码见 Vaadin 网站ThreadLocal Pattern 文章中的第二个代码示例。

      还有其他方法 - 使用 Spring 或 Guice 来创建和管理应用程序实例,但它们只有在您已经在使用这些框架时才有意义。

      另外值得注意的是,你可以通过调用Window#getApplication来访问一个Window所属的Application实例;但是,这种关联仅在将 Window 添加到应用程序时才进行,因此在构造函数中不可用。

      【讨论】:

      • 谢谢。我已经替换了单例应用程序,并且 Web 应用程序开始以正确的方式工作。
      猜你喜欢
      • 2018-08-31
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-01-20
      • 2015-02-02
      • 2022-10-24
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多