如何将当前的vaadin会话提供给线程池的旧线程?

How to provide current vaadin session to the old threads of thread pool?

我在理解 VaadinSession.getCurrent()

的引用时遇到 a 问题

Gets the currently used session. The current session is automatically defined when processing requests to the server and in threads started at a point when the current session is defined (see InheritableThreadLocal). In other cases, (e.g. from background threads started in some other way), the current session is not automatically defined.

具体以下几点对我来说很难理解,

... in threads started at a point when the current session is defined (see InheritableThreadLocal).

什么意思?

我的理解是如果thread是在new Session定义之前或者在oldsession中创建的,那么它不会引用当前新创建的会话。

目前我有Thread Pool并且一些线程指的是现在关闭的旧会话然后我将面临在这些线程中使用会话的问题。

我正在使用 springvaadin,特别是 @Async 方法调用。

@Async
public static methodX() {
    //I have used session inside it
}

问题是,thread1 已经被用来执行 methodX,现在我已经使用了会话 session1 并且在用户注销后这个 session1 将被关闭。

现在,当新用户登录到具有session2的系统并再次使用thread1执行此方法时,此方法仍然使用session1而不是session2 并且当方法试图从 closed session1.

获取数据时会产生问题

我的问题:

这意味着如果你在单独的线程中处理数据,你将没有当前会话:

所以这段代码:

Runtime runtime = Runtime.getRuntime();                 
final Process process = runtime.exec(action);
new Thread() {
    public void run() {
        try {
            System.out.println(VaadinSession.getCurrent());
        } catch(IOException ioe) {
            ioe.printStackTrace();
        }
    }
}.start();

在您的 vaadin 项目中将打印一个旧会话,即线程启动时的会话。

编辑

我认为 Vaadin 不能向旧线程提供新会话以避免数据损坏问题。我的意思是如果 5 个线程正在编辑同一个会话,你就会遇到问题...

你的解决方案是为池中的每个线程提供会话,但我真的不知道如何实现,Google 到目前为止没有给我答案。

编辑:另一种可能的解决方案

创建一个 class 以静态方式使用 HashMap<int, VaadinSession> 存储每个会话(使用 SessionListener)。

当你创建你的线程时,给他们一个他们需要使用的会话的id(id是你在HashMap中你想要的会话对应的键)。然后每次编辑、销毁会话等时,只需在 HashMap.

中编辑它

由于此 HashMap 的静态行为,您可以随时从任何线程访问它,您唯一需要的是线程中与您的会话对应的 int id。

问题是后台线程 VaadinSession(不要与 HttpSession 混淆)不可用。在 vaadin 的书中搜索后,我得出以下解决方案的结论。

要获得当前会话,我们有 VaadinSession.getCurrent()UI.getCurrent().getSession() 两者 returns 会话。

问题是在其他会话期间创建的旧线程无法访问当前会话,如引用中所述。这种情况仅在 @Async 调用时出现。

@Async
public void method() {
   //get id from session
}

应用程序加载后,多个 vaadin 请求可以使用该方法,并且 ThreadPool 的每个线程都会执行任务。

Thread - 1 executed method - used session 1
session 1 closed
session 2 defined
Thread - 1 again used to execute method
Thread - 1 executed method - used session 1 instead of new defined session 2

现在,在我的例子中,对于每个 vaadin 请求,我们都有新的 UI 实例。但是旧线程正在考虑的 UI 已过时,因为会话已关闭。

我已经从外部将 UI 实例传递给这个 异步 方法,就像这样。

@Async
public void method(UI ui) {
   UI.setCurrent(ui);
   UI.getCurrent().getSession();//Now I have latest session
}

UI.setCurrent(UI ui)方法的文档中也有说明,

The application developer can also use this method to define the current UI outside the normal request handling, e.g. when initiating custom background threads.