java - Servlet 中的构造函数和 Finalize() 方法

标签 java jakarta-ee servlets

据我们所知init()执行构造函数的工作和 destroy()与 Servlet 情况下的 Finalize 方法相同,并且拥有构造函数和 finalize() 没有任何害处。方法 Servlet .

现在的查询是:如果一个构造函数和一个 finalize()方法定义在Servlet中,它们会被调用吗?是否就像我们在构造函数中初始化的内容将被 init() 中的内容覆盖一样? ,或者根本不会调用构造函数?

最佳答案

首先进行小修正

让我们首先回顾一些假设。更多详细信息请参阅帖子的其余部分。

As we know init() does the job of constructor

不,事实并非如此。它有显着的不同,因为:

  • 声明抛出 ServletException
  • 声明一个 ServletConfig 参数, * 它调用其父构造函数(因为 Java 默认调用父构造函数的无参构造函数)。

对于最后一点,在一般情况下这并不重要,因为 ServletHttpServlet 不执行任何操作,但如果使用这些抽象类的扩展,那么你不应该假设他们也没有搞乱构造函数并在其中做一些事情。虽然您可以从 init() 中选择不调用父级 init(),但父级的无参数构造函数将始终被调用。

[...] and destroy() the same of finalize method

不,事实并非如此。

there is no harm having a constructor and finalize method in a servlet

如果构造函数和终结器中发生异常,可能会造成伤害,无论如何我肯定不建议使用它们,但建议坚持使用 init()destroy() 以符合规范。规范中未定义自定义构造函数和析构函数抛出的异常的异常处理规则,因此这些将是未定义的行为/特定于容器的行为。

will they be called?

你尝试过吗?会发生什么?

(是的:无参数构造函数将为每个新线程实例调用,并且终结器将被调用...每当 GC 愿意时。 )

is it like whatever we will initialize in constructor will be overriden with that in init() or constructor wont be called at all?

init() 不是构造函数。

您可以覆盖在构造函数中初始化的 init() 中的某些内容(例如成员变量),或者撤消/恢复在构造函数中执行的操作。不明白为什么这会有用,但你可能可以。但它们不会相互抵消,如果这就是你的意思的话。

为什么要这样做?

我在这里问自己的问题更多:

  • 为什么您觉得这里需要一个自定义构造函数?
  • 为什么你觉得这里需要一个终结器? (或者实际上是一般情况?)

Servlet 生命周期

取自 Java EE 6 教程的 Servlet Lifecycle 部分:

  1. If an instance of the servlet does not exist, the web container
    • Loads the servlet class.
    • Creates an instance of the servlet class.
    • Initializes the servlet instance by calling the init method. Initialization is covered in Creating and Initializing a Servlet.
    • Invokes the service method, passing request and response objects. Service methods are discussed in Writing Service Methods.
  2. If it needs to remove the servlet, the container finalizes the servlet by calling the servlet’s destroy method. For more information, see Finalizing a Servlet.

[...]

Any number of exceptions can occur when a servlet executes. When an exception occurs, the web container generates a default page containing the following message:

A Servlet Exception Has Occurred

如何正确init()

让我们回顾一下 init() 上的 Javadoc (强调我的)

Called by the servlet container to indicate to a servlet that the servlet is being placed into service.

The servlet container calls the init method exactly once after instantiating the servlet. The init method must complete successfully before the servlet can receive any requests.

The servlet container cannot place the servlet into service if the init method

  • Throws a ServletException
  • Does not return within a time period defined by the Web server

因此,请小心不要在 init() 中执行任何过于耗时的操作,以及只需要执行一次的操作。如果所有请求都需要执行此操作,则在请求处理方法中执行此操作(例如 doGet()doPost()...)。

另请参阅Creating and Initializing a ServletJava EE 6 Tutorial (and for Java EE 5)。

如何正确destroy()

Called by the servlet container to indicate to a servlet that the servlet is being taken out of service. This method is only called once all threads within the servlet's service method have exited or after a timeout period has passed. After the servlet container calls this method, it will not call the service method again on this servlet.

This method gives the servlet an opportunity to clean up any resources that are being held (for example, memory, file handles, threads) and make sure that any persistent state is synchronized with the servlet's current state in memory.

另请参阅Finalizing a ServletJava EE 6 Tutorial ( and for Java EE 5 )(当然,他们这里的用词很糟糕......)。

有关历史 Servlet 设计以及为什么尝试绕过它是一件坏事 (TM) 的更多信息!

参见http://oreilly.com/catalog/jservlet/chapter/ch03.html#15894 :

Why not use a constructor instead? Well, in JDK 1.0 (for which servlets were originally written), constructors for dynamically loaded Java classes (such as servlets) couldn't accept arguments. So, in order to provide a new servlet any information about itself and its environment, a server had to call a servlet's init() method and pass along an object that implements the ServletConfig interface. Also, Java doesn't allow interfaces to declare constructors. This means that the javax.servlet.Servlet interface cannot declare a constructor that accepts a ServletConfig parameter. It has to declare another method, like init(). It's still possible, of course, for you to define constructors for your servlets, but in the constructor you don't have access to the ServletConfig object or the ability to throw a ServletException.

特别注意最后一句:

[...] but in the constructor you don't have access to the ServletConfig object or the ability to throw a ServletException.

因此,在 servlet 的构造函数中执行任何操作都将是:

  • 不切实际,
  • 但大多非常危险!!

关于java - Servlet 中的构造函数和 Finalize() 方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17021689/

相关文章:

tomcat - 在 cloudbees 中启动应用程序时,无法将 org.zkoss.zk.ui.http.DHtmlLayoutServlet 转换为 javax.servlet.Servle

java - JSpinner stateChanged 是如何工作的?

java - 如何将文本写入文件而不等待文件关闭

jakarta-ee - Java Web 应用程序中的 META-INF 和 WEB-INF 中的 INF 是什么?

jakarta-ee - 如何使用 Gradle 更新现有的 War/Jar/Zip 文件?

java - @MultipartForm 如何获取原始文件名?

java - getActionView 已弃用?

java - 选项卡布局的选项卡不显示任何内容

java - 哪个类提供了 getRequestDispatcher() 方法的实现

java - java中如何维护session