为什么我们不能使用构造函数本身来初始化一个servlet?

6 浏览
0 Comments

为什么我们不能使用构造函数本身来初始化一个servlet?

为什么我们在Servlet中必须重写init()方法,而我们可以在构造函数中进行初始化,并且在调用构造函数时,Web容器将ServletConfig引用传递给Servlet?\n当然,容器必须使用反射来实现这个,但是无论如何容器都必须使用反射来调用一个简单的无参构造函数。

0
0 Comments

为什么我们不能使用构造函数来初始化一个servlet?

一个原因是在构造函数中无法访问ServletConfig对象。ServletConfig对象是在构造函数被调用之后和init()方法被调用之前创建的。因此,你不能在构造函数中访问servlet的初始化参数。

解决这个问题的方法是在init()方法中进行初始化操作。在init()方法中,你可以通过调用getServletConfig()方法来获取ServletConfig对象,并通过它来访问初始化参数。

下面是一个示例代码,展示了如何在init()方法中初始化一个servlet:

public class MyServlet extends HttpServlet {
    private String myParam;
    public void init() {
        ServletConfig config = getServletConfig();
        myParam = config.getInitParameter("myParam");
        // 在这里进行初始化操作
    }
}

在上述代码中,init()方法通过调用getServletConfig()方法获取ServletConfig对象,并通过它来获取名为"myParam"的初始化参数。然后,你可以在init()方法中进行初始化操作,将获取到的初始化参数赋值给成员变量myParam。

通过在init()方法中进行初始化操作,我们可以确保在初始化时能够访问到ServletConfig对象和初始化参数,从而解决了在构造函数中无法访问这些对象和参数的问题。

0
0 Comments

为什么我们不能使用构造函数来初始化一个servlet?

Servlet对象有一个明确定义的生命周期,其中创建和初始化步骤是不同的。通常情况下,您不希望在构造函数中执行繁重且不可靠的工作,例如获取数据库连接池或初始化缓存。您有机会在Servlet对象成功创建后执行这些操作。

此外,这里有一个历史原因:

在JDK 1.0中(servlet最初编写的版本),动态加载的Java类(如servlet)的构造函数不能接受参数。因此,为了向新的servlet提供关于自身和环境的任何信息,服务器必须调用servlet的init()方法并传递一个实现了ServletConfig接口的对象。

另外,Java不允许接口声明构造函数。这意味着javax.servlet.Servlet接口不能声明一个接受ServletConfig参数的构造函数。它必须声明另一个方法,比如init()。当然,您仍然可以为您的servlet定义构造函数,但在构造函数中,您无法访问ServletConfig对象或能够抛出ServletException异常。

解决方法:使用init()方法来执行初始化工作,而不是在构造函数中执行。这样可以确保在Servlet对象成功创建后再进行初始化,同时也可以获得ServletConfig对象的访问权限。

下面是一个示例代码,演示了如何在servlet中使用init()方法进行初始化:

public class MyServlet extends HttpServlet {
  
  @Override
  public void init() throws ServletException {
    // Perform initialization here
    // e.g. get DB connection pool, initialize cache
  }
  
  // Other methods and logic here
  
}

通过使用init()方法,我们可以在servlet对象创建后执行初始化操作,并且可以访问ServletConfig对象以及能够抛出ServletException异常。这种方式更符合servlet的生命周期和Java语言的限制。

0
0 Comments

为什么我们不能使用构造函数自身来初始化一个servlet?这个问题的出现原因是因为构造函数不能作为接口的一部分,因此在Servlet API中无法“正式”指定它,与普通方法不同。此外,由于Java没有析构函数,因此无论如何都需要一个destroy方法,因此定义相应的init方法使API更加一致和易于使用。

使用反射来检测/验证构造函数参数只会增加不必要的复杂性,我看不到任何附加值。

好吧,反射无论如何都会被使用,附加值是你可以使你的servlets不可变。有很多类的初始化是在构造函数中进行的,但是它们有相应的close方法;几乎每个流类都是这样工作的。

因为你不应该在servlet中存储(非静态)数据,所以不可变性并不重要。流类是一个很好的例子;然而请注意,这些是具体类,而不是接口。

在servlet中有很好的理由拥有(不可变的)非静态状态。ServletConfig的整个意义在于您可以多次实例化相同的servlet并使其执行(稍微)不同的操作。

尽管不相关,但是我们有一个可以用作析构函数的finalize()方法吗?

抱歉,我不理解什么是不可变性...你能解释一下吗?

finalize()不是析构函数,实际上不应该使用。请参见What is the purpose of Finalization in java?,以及更多详情,请参见this article.

请注意,ServletConfig并不强制使用非静态数据成员。

不可变性意味着在初始化完成后(在Java中,这意味着构造函数完成后),您不能更改对象。这通常被认为是一件好事,因为它使得代码更容易理解。

如果将内容放入静态字段中,当将同一个servlet类映射到具有不同配置的几个不同servlet时,会发生什么?(答案:最后加载的servlet将覆盖先前加载的servlet设置的值。)

好吧,我的评论表达不清楚 - 只需要忽略“非静态”。

0