HttpServlet为什么实现Serializable?


77

在我对Servlet的理解中,该Servlet将由Container实例化,其init()方法将被调用一次,并且Servlet将像单例一样存活,直到JVM关闭。

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

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


Answers:


59

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

实际上,我从未听说过有容器可以做到这一点,所以它实际上只是早期J2EE糟糕时期的遗留物。我不用担心。


1
但是,当它是线程安全的并且没有会话状态时,谁需要钝化servlet?
2013年

1
它以使群集服务器不会失败和整个的情况下,映射会话O故障类似的bug进行验证,issues.apache.org/bugzilla/show_bug.cgi?id=30809
开发

2
@dev错误是关于不可序列化的会话属性,而不是关于servlet的任何序列化。
Arend v。Reinersdorff

可以通过<distributable />进入web.xml来触发。
阿基米德·特拉哈诺

11

HttpServlet应该序列化到磁盘上,并在重新启动servlet容器后仍然存在。例如,tomcat允许您设置标志来启用这种生存。下一个选项是使用JNDI进行传输。这不是垃圾,它仅在极端用例中使用。


JNDI是设置不可序列化字段的唯一正确方法吗?太恐怖了 :(
Trejkaz

1

Google似乎建议这样做,以便容器作者可以选择。

您是正确的,该servlet不应该包含特定于会话的成员,实际上,我认为您希望尽可能少的状态。如果您将所有内容存储在Session或ServletConfig中,那么我认为您将能够幸免于序列化。


2
那么,Session比servlet更有可能被序列化,因此将其存储在其中并不能减轻问题。
skaffman's

1
@matt b:关注的不是会话特定的状态,而是servlet自己的依赖项(例如,服务层对象)
Andrew Swan

0

就像将Session对象序列化以保留那些提供集群选项的Servlet容器的缓存一样,容器可能会有一个选项将Servlet实例也传输到另一个集群节点。我只是在猜这里


-3

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

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

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

  • 容器必须接受实现Serializable接口的对象
  • 会话的迁移将由特定于容器的设施处理。

分布式Servlet容器必须为对象无法抛出的IllegalArgumentException抛出异常,该对象不能支持迁移存储它们的会话所必需的机制

分布式Servlet容器必须支持迁移实现Serializable的对象所必需的机制 。

(...)

容器提供程序可以通过将会话对象及其内容从分布式系统的任何活动节点移动到系统的其他节点,来确保可伸缩性和服务质量功能(如负载平衡和故障转移)如果分布式容器保留或迁移会话以提供服务质量功能,则它们不限于使用本机JVM序列化机制来序列化HttpSession及其属性。如果开发人员实现了容器,则不能保证容器将在会话属性上调用readObject和writeObject方法,但是可以保证保留其属性的Serializable关闭


3
这是一个误导性的答案。Servlet实例通常不存储在会话中。
BalusC
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.