简体   繁体   English

Servlet中的构造方法和finalize()方法

[英]Constructor and finalize() method in Servlet

As we know init() does the job of constructor and destroy() the same of finalize method in case of servlet and there is no harm having a constructor and finalize() method in a Servlet . 正如我们所知道init()确实构造的工作和destroy()相同的finalize方法中的servlet的情况和存在具有一个构造函数和无伤害finalize()的方法Servlet

Now the query is: if a constructor and a finalize() method are defined in a Servlet, will they be called? 现在的查询是:如果在Servlet中定义了构造函数和finalize()方法,将调用它们吗? Is it like whatever we will initialize in constructor will be overriden with that in init() , or the constructor wont be called at all? 就像我们将在构造函数中初始化的任何东西都将被init()那个覆盖一样,还是根本不会调用该构造函数?

Small Corrections First 小修正首先

Let's review some assumptions first. 让我们先回顾一些假设。 More details in the rest of the post. 在后面的文章中有更多详细信息。

As we know init() does the job of constructor 我们知道init()可以完成构造函数的工作

No, it doesn't. 不,不是。 It's significantly different as it: 它有很大的不同,因为:

  • declares a throws ServletException , 声明throws ServletException
  • declares a ServletConfig parameter, * it invokes its parent constructor (as Java invokes the parent's no-arg constructor by default). 声明一个ServletConfig参数,*调用其父构造函数(默认情况下,Java调用父的no-arg构造函数)。

For that last point, it won't matter in your general case as Servlet and HttpServlet don't do anything, but if using extensions of these abstract clases then you shouldn't assume that they didn't also mess up with the constructors and do things in them. 对于最后一点,在一般情况下这无关紧要,因为ServletHttpServlet不执行任何操作,但是,如果使用这些抽象类的扩展名,则您不应该假定它们也不会干扰构造函数,并且在他们身上做事。 While you can choose from your init() to NOT invoke the paren't init() , the parent's no-arg constructor will always be invoked. 虽然您可以从init()选择不调用未init() ,但始终会调用父级的no-arg构造函数。

[...] and destroy() the same of finalize method [...]和destroy()与finalize方法相同

No, it doesn't. 不,不是。

there is no harm having a constructor and finalize method in a servlet 在servlet中具有构造函数和finalize方法没有害处

There may be harm if exceptions occur in your constructor and finalizer, and in any case I surely wouldn't recommend using those, but suggest sticking to init() and destroy() to comply to the spec. 如果在构造函数和终结器中发生异常, 可能会造成危害,并且无论如何我肯定不建议使用这些异常,而是建议坚持使用init()destroy()来遵守规范。 The exception handling rules for exceptions thrown from your custom constructor and destructors aren't defined in the specification, so these would be undefined behavior / container-specific. 从您的自定义构造函数和析构函数抛出的异常的异常处理规则未在规范中定义,因此它们将是未定义的行为/特定于容器的。

will they be called? 他们会被称为吗?

Did you try? 你试过了吗? What happens? 怎么了?

(Yes: the no-arg constructor will called for each new thread instance, and the finalizer will be called... whenever the GC will feel like it. ) (是的:每当新的线程实例都将为每个新线程实例调用no-arg构造函数,并且在终结器将被调用时…… 只要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() isn't a constructor. init()不是构造函数。

You may be able to override something in init() that was initialized in the constructor (eg a member variable), or undo/revert actions that you performed in the constructor. 您可能可以覆盖init()中在构造函数中初始化的某些内容(例如,成员变量),或者撤消/还原在构造函数中执行的操作。 Don't see a reason why that would be useful, but you possibly could. 没有看到一个有用的理由,但您可能会有用。 But they won't cancel each other out, if that's what you mean. 但是,如果您的意思是这样,他们不会互相抵消。

Why even want to do that? 为什么还要这么做?

The questions I ask myself here are more: 我在这里问自己的问题更多:

  • Why do you feel you need a custom constructor here? 为什么觉得这里需要自定义构造函数?
  • Why do you feel you need a finalizer here? 为什么觉得这里需要终结器? (or in general, actually?) (或者实际上是?)

Servlet Lifecycle Servlet生命周期

Taken from the Java EE 6 Tutorial's section on the Servlet Lifecycle : 取自Servlet Lifecycle的Java EE 6教程部分:

  1. If an instance of the servlet does not exist, the web container 如果servlet的实例不存在,则Web容器
    • Loads the servlet class. 加载servlet类。
    • Creates an instance of the servlet class. 创建servlet类的实例。
    • Initializes the servlet instance by calling the init method. 通过调用init方法初始化servlet实例。 Initialization is covered in Creating and Initializing a Servlet. 创建和初始化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. 如果需要删除该servlet,则该容器通过调用servlet的destroy方法来最终确定该servlet。 For more information, see Finalizing a Servlet. 有关更多信息,请参见完成Servlet。

[...] [...]

Any number of exceptions can occur when a servlet executes. 执行servlet时,可以发生任何数量的异常。 When an exception occurs, the web container generates a default page containing the following message: 发生异常时,Web容器将生成一个默认页面,其中包含以下消息:

A Servlet Exception Has Occurred 发生了Servlet异常

How to properly init() 如何正确init()

Let's the review the Javadoc on init() (emphasis mine) 让我们回顾一下init()上的Javadoc(重点是我的)

Called by the servlet container to indicate to a servlet that the servlet is being placed into service. 由Servlet容器调用以向Servlet 指示该Servlet正在投入使用。

The servlet container calls the init method exactly once after instantiating the servlet . 实例化servlet后 ,servlet容器仅调用一次init方法。 The init method must complete successfully before the servlet can receive any requests. servlet可以接收任何请求之前,init方法必须成功完成。

The servlet container cannot place the servlet into service if the init method 如果使用init方法,则servlet容器无法将servlet投入使用

  • Throws a ServletException 抛出ServletException
  • Does not return within a time period defined by the Web server 在Web服务器定义的时间段内不返回

So, be careful not do anything too consuming in your init() , and things that need to be done only once. 因此,请注意不要在init()做任何过于消耗的事情,而只需要执行一次即可。 If it's something that needs to be done for all requests, then do it in the request processing method (eg doGet() , doPost() , ...). 如果需要对所有请求执行此操作,请使用请求处理方法(例如doGet()doPost() ,...)进行操作。

See also Creating and Initializing a Servlet in the Java EE 6 Tutorial ( and for Java EE 5 ). 另请参阅Java EE 6教程以及Java EE 5 )中的创建和初始化Servlet

How to properly destroy() 如何正确destroy()

Called by the servlet container to indicate to a servlet that the servlet is being taken out of service. 由Servlet容器调用以向Servlet 指示该Servlet正在退出服务。 This method is only called once all threads within the servlet's service method have exited or after a timeout period has passed. 仅当servlet的service方法中的所有线程都已退出或经过超时时间后,才调用此方法。 After the servlet container calls this method, it will not call the service method again on this servlet. servlet容器调用此方法后,它将不再在该servlet上再次调用service方法。

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. 此方法使Servlet有机会清除所持有的任何资源(例如,内存,文件句柄,线程),并确保任何持久状态都与Servlet在内存中的当前状态同步。

See also Finalizing a Servlet in the Java EE 6 Tutorial ( and for Java EE 5 ) (granted, poor choice of words from them here...). 另请参见Java EE 6教程对于Java EE 5 )中的Servlet的完成 (此处允许您从单词中选择较差的内容,...)。

More Information on the Historical Servlet Design and Why Trying to Bypass it is a BAD THING (TM)! 有关历史Servlet设计以及为何试图绕过它的更多信息是不好的事情(TM)!

See http://oreilly.com/catalog/jservlet/chapter/ch03.html#15894 : 参见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. 好吧,在JDK 1.0(最初为其编写servlet)中, 动态加载的Java类(例如servlet)的构造函数不能接受参数。 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. 因此,为了向新的Servlet提供有关其自身及其环境的任何信息,服务器必须调用Servlet的init()方法并传递实现ServletConfig接口的对象。 Also, Java doesn't allow interfaces to declare constructors. 另外, Java不允许接口声明构造函数。 This means that the javax.servlet.Servlet interface cannot declare a constructor that accepts a ServletConfig parameter . 这意味着javax.servlet.Servlet接口无法声明接受ServletConfig参数的构造函数 It has to declare another method, like init(). 它必须声明另一个方法,例如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. 当然,仍然可以为Servlet定义构造函数, 但是在构造函数中,您无权访问ServletConfig对象或抛出ServletException的能力。

Pay especially attention to the last sentence: 请特别注意最后一句话:

[...] but in the constructor you don't have access to the ServletConfig object or the ability to throw a ServletException. [...]但在构造函数中,您无权访问ServletConfig对象或抛出ServletException的功能。

So doing anything in the servlet's constructor would be: 因此,在servlet的构造函数中执行任何操作将是:

  • impractical, 不切实际的,
  • but mostly quite dangerous!! 但是大多很危险!

I'm pretty certain that servlets will follow the normal object lifecycle and the constructor will be called. 我非常确定servlet将遵循正常的对象生命周期,并且调用构造函数。

The existence of an init method means that you can include initialisation code that relies on other parts of the framework having also been initialized. 初始化方法的存在意味着您可以包括依赖于框架也已初始化的其他部分的初始化代码。 It is called in a known point in the construction of the framework. 在框架的构造中,在已知的地方调用它。

Finalize may be called - it'll have all the same problems associated with finalize on all java onjects 可以调用Finalize-与所有java onject的finalize相关的所有相同问题

Constructor creates an object of the servlet . 构造函数创建servlet的对象。 init() is used to initialize the servlet object. init()用于初始化servlet对象。 The container passes a reference of ServletConfig to the servlet object in the init(ServletConfig) method so that the Servlet has access to the ServletConfig and ServletContext . 容器将ServletConfig的引用传递给init(ServletConfig)方法中的Servlet对象,以便Servlet可以访问ServletConfigServletContext You can override a no-arg init() method to execute any initialization code specific to your Servlet. 您可以重写no-arg init()方法来执行任何特定于Servlet的初始化代码。 Without the init() method , your Servlet will not have access to its init params. 没有init()方法,您的Servlet将无法访问其init参数。

Since destroy() is the method that the container uses to cleanup resources held by Servlet, you should use it. 由于destroy()是容器用来清除Servlet拥有的资源的方法,因此应该使用它。 The finalize() method should be regarded as the absolute last chance to clean up as an object is removed from memory, and not the normal routine cleanup method.Since destroy() is called while the Servlet container still has a reference to the Servlet object, it will be called before the GC process ever gets around to calling finalize() . finalize()方法应视为从内存中删除对象的绝对的最后一次清除机会,而不是正常的常规清理方法。因为在Servlet容器仍具有对Servlet对象的引用的情况下调用了destroy() ,它将在GC进程调用finalize()之前被调用。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM