两个级别的范围
请参阅Roland Krüger 的这篇文章,了解 Vaadin 7 中的范围级别以及VaadinSession和UI类。他包含了与 Vaadin 6 的比较。好文章除了手动锁定的讨论在 Vaadin 7.1 中已经过时(请参阅我在该页面上的评论,并查看我对类似问题的回答)。
了解虽然 Vaadin 6 和 Vaadin 7 的大部分内容相似或相同,但在这个主题上 6 和 7 完全不同,涉及不同的架构和不同的类。
请注意,我们讨论VaadinSession
的是 HTTP 或Servlet 会话。VaadinSession 包装或包含 Servlet 会话,因此我们不必关心 Servlet 级别。
此 VaadinSession 代表单个用户的工作会话。用户打开了一个或多个窗口/选项卡(UI
实例)。

上图有点过于简单了。这里有一个更详细的。

多个窗口
Vaadin 7 支持在同一个 Vaadin 应用程序上打开多个浏览器窗口/选项卡。这是 Vaadin 6 架构的重大变化。
每个浏览器窗口/选项卡的内容是您的UI
子类的一个实例。所有这些实例都属于同一个VaadinSession
. 如果用户单击浏览器窗口/选项卡上的重新加载功能,该UI
实例将被销毁并实例化一个新实例。但VaadinSession
经久不衰。添加@PreserveOnRefresh
注释会更改该行为以保留相同的 UI 实例,但这不是重点。
关键是 Vaadin 7 有两个级别的范围:
VaadinSession
(你的整个应用程序)
UI
(每个浏览器窗口/选项卡)。
您可能希望在任一级别存储数据。例如,用户登录/身份验证信息应该放在 VaadinSession 中。
开启状态UI
要在 UI 上存储数据,请将字段或集合添加到 UI 子类。简单明了。
开启状态VaadinSession
要在 VaadinSession 上存储数据,请调用setAttribute
和getAttribute
. 您将不得不转换结果。很简单,除了一个问题:线程安全。
线程安全
您可以手动管理锁定以同时保护 VaadinSession。但是,如果您遵循记录在案的规则,Vaadin 会为您提供线程安全保护。
主线程
如果从通常的主用户界面线程修改 VaadinSession,则没有问题。您从主线程在 Vaadin 中所做的大多数事情都已经影响到 VaadinSession 对象。这就是您的应用程序所在的位置。因此,线程安全锁定已经由 Vaadin 自动提供。
其他主题
如果从另一个线程使用 VaadinSession,请在Runnable中进行调用,然后将其传递给access
UI 或 VaadinSession 对象上的方法。如果影响除了会话之外的任何用户界面布局或小部件,请access
在 UI 方法上调用该方法。如果只影响会话而不影响用户界面,请将您的 Runnableaccess
方法传递给 VaadinSession。
第三级范围:应用程序范围
仅供参考,您可以使用更广泛的范围。如果您有“全局”数据或对象要在所有用户的会话中共享应用程序范围,则可以访问该ServletContext
对象。“上下文”是指你的网络应用程序的世界,你的网络应用程序可以访问的东西。您的 Vaadin 应用程序有一个ServletContext
由您的 Servlet 容器自动实例化的对象。调用这对方法 ,getAttribute
和setAttribute
, 来存储Object
你拥有的任何东西。
有关更多信息,请参阅我的这个问答,如何ServletContext
从 Vaadin 7 应用程序中访问?.
用文字总结(和下图):一个 Servlet 容器,如 Tomcat 或 Jetty 可以运行一个或多个 Vaadin Web 应用程序。每个 Web 应用程序都有一个ServletContext
由容器自动管理的对象,其中get/setAttribute
方法可以存储您选择的任何对象。每个 Vaadin Web 应用程序VaadinSession
对于每个用户的当前工作会话都有一个对象。每个VaadinSession
对象包含一个或多UI
个子类实例,表示在 Web 浏览器的窗口/选项卡(或 Portlet 视图区域)中看到的内容。每个UI
子类实例可以有任意数量的成员变量,就像任何POJO一样。

提示:如果您愿意,您的 Runnable 可以使用 Java 8 中新的更短的 Lambda 语法。NetBeans 8 甚至会建议这样做。