为什么会话变量必须是可序列化的?

Why does a session variable have to be serializable?

尝试存储自定义对象的列表变量时
session.setAttribute 抱怨变量不可序列化。

您的整个 servlet 会话可以随时序列化到磁盘或其他存储。所以里面的所有对象都必须是可序列化的。

servlet 容器(您的应用程序服务器,如 Tomcat)可能希望将会话信息存储到磁盘。这将帮助您在服务器重新启动时保留用户会话,并且如果它不将每个会话对象都存储在内存中,而是仅在需要时查找它,还允许它更有效地管理内存。

因此您的会话对象需要 Serializable

正如其他答案所解释的那样,要求会话变量可序列化的目的是允许容器框架使用对象序列化来:

  • 在分布式 Web 服务实现中的服务器实例之间迁移会话
  • 在服务器重新启动或节省内存时保持会话。

但有趣的是,Servlet 3.0 规范实际上并不需要这样做。相反,它说:

7.7.2 Distributed Environments

Within an application marked as distributable, all requests that are part of a session must be handled by one JVM at a time. The container must be able to handle all objects placed into instances of the HttpSession class using the setAttribute or putValue methods appropriately. The following restrictions are imposed to meet these conditions:

  • The container must accept objects that implement the Serializable interface.

  • The container may choose to support storage of other designat ed objects in the HttpSession, such as references to Enterprise JavaBeans components and transactions.

  • Migration of sessions will be handled by container-specific facilities. The distributed servlet container must throw an IllegalArgumentException for objects where the container cannot support the mechanism necessary for migration of the session storing them. The distributed servlet container must support the mechanism necessary for migrating objects that implement Serializable.

These restrictions mean that the Developer is ensured that there are no additional concurrency issues beyond those encountered in a non-distributed container. The Container Provider can ensure scalability and quality of service features like load-balancing and failover by having the ability to move a session object, and its contents, from any active node of the distributed system to a different node of the system.

如果我们仔细分析它,它是说:

  • 分布式容器必须支持对象序列化作为在会话中迁移对象的一种方式。

  • 应用程序不需要标记为可分发。

  • 容器不需要是分布式容器。

  • 容器可能支持其他迁移对象的方法。

那么这是什么意思呢?好吧,我认为这意味着您的会话对象实现 Serializable 的明显要求源于您对容器的选择以及您选择实现 webapp 的方式。假设您可以更改这些选择。

由于要在不同的请求范围内访问模型,所以需要将其存储在http会话中。根据JPA实体class的要求,即 涉及http会话,必须实现Serializable接口。