Java 为什么HttpServlet实现可序列化?

Java 为什么HttpServlet实现可序列化?,java,session,servlets,serializable,Java,Session,Servlets,Serializable,在我对Servlet的理解中,Servlet将由容器实例化,它的init()方法将被调用一次,Servlet将像一个单独的个体一样存在,直到JVM关闭 我不希望我的servlet被序列化,因为当应用服务器恢复或正常启动时,它将被构造为新的。servlet不应该包含特定于会话的成员,因此将其写入磁盘并重新实例化是没有意义的。 这有实际用途吗 我担心的是,我在其中放置了一些不可序列化的字段,然后我的应用程序会在生产环境中神秘地失败,在生产环境中会发生不同类型的会话复制。从技术上讲,我相信servle

在我对Servlet的理解中,Servlet将由容器实例化,它的
init()
方法将被调用一次,Servlet将像一个单独的个体一样存在,直到JVM关闭

我不希望我的servlet被序列化,因为当应用服务器恢复或正常启动时,它将被构造为新的。servlet不应该包含特定于会话的成员,因此将其写入磁盘并重新实例化是没有意义的。 这有实际用途吗


我担心的是,我在其中放置了一些不可序列化的字段,然后我的应用程序会在生产环境中神秘地失败,在生产环境中会发生不同类型的会话复制。

从技术上讲,我相信servlet容器可以将servlet对象“钝化”到磁盘,以与EJB会话bean类似的方式进行。因此,如果您的应用程序因不可序列化字段而失败,那么您的问题是正确的


实际上,我从来没有听说过容器会这样做,所以它实际上只是早期J2EE糟糕的旧时代遗留下来的包袱。我不会担心的。

谷歌似乎建议这样做是为了让容器作者可以选择,如果他们想要的话


您认为servlet不应该包含特定于会话的成员,这是正确的,事实上,我认为您需要尽可能少的状态。如果将所有内容存储在Session或ServletConfig中,我认为您将能够在序列化后继续生存。

就像会话对象被序列化以在提供集群选项的servletcontainers的缓存中继续生存一样,容器也可能有一个选项将Servlet实例传输到另一个集群节点??我只是猜测这里的HttpServlet应该被序列化到磁盘,并在servlet容器重新启动后存活下来。例如,tomcat允许您设置允许这种生存的标志。下一个选项是使用JNDI进行传输。这不是垃圾,它只在极端使用情况下使用。

可序列化在分布式环境中用作会话属性的标记接口。

SRV.7.7.2分布式环境(JSR-154)

在标记为可分发的应用程序中,所有 会话的一部分必须由一个Java虚拟机处理 (“JVM”)一次。容器必须能够处理所有对象 使用setAttribute将其放置到HttpSession类的实例中 或者适当地使用值方法。以下限制是: 为满足这些条件而施加的:

  • 容器必须接受实现可序列化接口的对象
  • 会话迁移将由特定于容器的设施处理
分布式servlet容器必须抛出 无法使用容器的对象的IllegalArgumentException 支持迁移会话存储所需的机制 他们

分布式servlet容器必须支持必要的机制 对于 迁移实现可序列化的对象

(……)

容器提供者可以确保可伸缩性和服务质量 通过实现负载平衡和故障切换等功能 从会话的任何活动节点移动会话对象及其内容 分布式系统到系统的其他节点。如果是分布式的 容器保存或迁移会话以提供高质量的 服务特性,它们不限于使用本机JVM 序列化HttpSessions的序列化机制及其应用 属性。开发人员不能保证容器会调用 会话属性上的readObject和writeObject方法 实现它们,但保证 它们的属性将被保留


会话比servlet更有可能被序列化,因此将其存储在那里并不能缓解问题。@matt b:问题不在于会话特定的状态,而在于servlet自身的依赖关系(例如服务层对象)。这是一个误导性的答案。servlet实例通常不存储在会话中。但是谁需要钝化servlet,因为它应该是线程安全的,并且没有会话状态?这样可以使群集服务器不会失败,并在o失败时映射会话。类似的错误验证了它,@dev该错误是关于不可序列化的会话属性,与servlet的任何序列化无关。这可以通过在web.xml中使用
触发。类似:JNDI是设置不可序列化字段的唯一正确方法吗?太可怕了(