HttpServlet为啥要实现Serializable?
Posted
技术标签:
【中文标题】HttpServlet为啥要实现Serializable?【英文标题】:Why does HttpServlet implement Serializable?HttpServlet为什么要实现Serializable? 【发布时间】:2010-09-15 20:04:57 【问题描述】:在我对Servlet的理解中,Servlet会被Container实例化,它的init()
方法会被调用一次,在JVM关闭之前,Servlet会像单例一样存活。
我不希望我的 servlet 被序列化,因为它会在应用服务器恢复或正常启动时重新构建。 servlet 不应包含特定于会话的成员,因此将其写入磁盘并重新实例化是没有意义的。 这个有实际用途吗?
我担心的是,我在其中放置了一些不可序列化的字段,然后我的应用程序将在生产环境中神秘地失败,在那里会发生不同类型的会话复制。
【问题讨论】:
类似:Purpose of Serialization in webapplication 【参考方案1】:Serializable 用作分布式环境中会话属性的标记接口。
SRV.7.7.2 分布式环境 (JSR-154)
在标记为 distributable 的应用程序中,所有请求 是会话的一部分,必须由一个 Java 虚拟机处理 (“JVM”)一次。容器必须能够处理所有对象 使用 setAttribute 放入 HttpSession 类的实例中 或适当的 putValue 方法。以下限制是 强制满足这些条件:
容器必须接受实现 Serializable 接口的对象。 会话的迁移将由特定于容器的设施处理。分布式 servlet 容器必须抛出一个 容器不能的对象的 IllegalArgumentException 支持迁移会话存储所需的机制 他们。
分布式 servlet 容器必须支持必要的机制 为了 迁移实现 Serializable 的对象。
(...)
Container Provider 可以确保可扩展性和服务质量 具有负载平衡和故障转移等功能 从会话的任何活动节点移动会话对象及其内容 分布式系统到系统的不同节点。 如果分布式 容器保留或迁移会话以提供质量 服务功能,它们不限于使用本机 JVM 用于序列化 HttpSession 的序列化机制及其 属性。开发人员不能保证容器会调用 会话属性上的 readObject 和 writeObject 方法,如果它们 实现它们,但保证 Serializable 闭包 它们的属性将被保留。
【讨论】:
这是一个误导性的答案。 servlet 实例通常不存储在会话中。【参考方案2】:HttpServlet 应该被序列化到磁盘并在 servlet 容器重新启动后继续存在。例如,tomcat 允许您设置启用这种生存的标志。下一个选项是使用 JNDI 传输。这不是垃圾,它只用于极端用例。
【讨论】:
JNDI 是设置不可序列化字段的唯一正确方法吗?太可怕了。 :(【参考方案3】:就像 Session 对象被序列化以便为那些提供集群选项的 servlet 容器保留缓存一样,容器可能有一个选项可以将 Servlet 实例也传输到另一个集群节点?我只是在这里猜测
【讨论】:
【参考方案4】:Google 似乎建议这样做是为了让容器作者可以根据需要进行选择。
你是正确的,servlet 不应该包含特定于会话的成员,事实上我认为你希望尽可能少的状态。如果您将所有内容存储在 Session 或 ServletConfig 中,我认为您将能够在序列化中幸存下来。
【讨论】:
那么 Session 比 servlet 更有可能被序列化,因此将其存储在那里不会缓解问题。 @matt b:关注的不是特定于会话的状态,而是 servlet 自身的依赖项(例如服务层对象)【参考方案5】:从技术上讲,我相信允许 servlet 容器将 servlet 对象“钝化”到磁盘,这与 EJB 会话 bean 可以采用的方式类似。因此,如果您的应用程序由于不可序列化的字段而失败,您问这个问题是正确的。
在实践中,我从未听说过容器会这样做,因此它实际上只是早期 J2EE 糟糕的旧时代遗留下来的包袱。我不会担心的。
【讨论】:
但是谁需要钝化一个 servlet,什么时候它应该是线程安全的,并且没有会话状态? 这是为了使集群服务器不会失败并映射会话以防万一失败类似的错误验证它,issues.apache.org/bugzilla/show_bug.cgi?id=30809 @dev 这个错误是关于不可序列化的会话属性,而不是关于任何 servlet 的序列化。 这可以通过在 web.xml 中包含<distributable />
来触发。
其实我在现实生活中经历过:IBM Websphere 就是这样做的……以上是关于HttpServlet为啥要实现Serializable?的主要内容,如果未能解决你的问题,请参考以下文章
创建一个类去实现javax.servlet.servlet接口,为啥报错
为啥代理下的getContextPath()返回的是HttpServlet内部的内部路径,而不是Filter内部的路径?
为啥我们需要在创建 java web 时为放入服务器的类实现 Serializable [关闭]