我们可以将init方法的目的替换为servlet构造函数吗?

时间:2011-09-28 09:03:40

标签: java servlets

我们可以将init方法替换为servlet构造函数吗? 我的问题是为什么servlet需要一个单独的方法int(ServletConfig config)用于初始化,我们可以通过让参数化构造函数let XServlet(ServletConfig config)来实现相同的东西,并且容器可以调用它。

6 个答案:

答案 0 :(得分:5)

可能是因为您无法在接口中为构造函数指定参数签名。

答案 1 :(得分:2)

在构造函数中执行逻辑通常被认为是一种不好的做法(它应该只初始化字段并以一致的状态创建对象)。它也使测试更难。

执行注入也更加困难 - 使用init时,容器可以创建servlet,注入依赖项并运行init。使用构造函数,您可能希望已经设置了所有依赖项。 Wicket通过将超类构造函数中的Spring bean注入到页面类中来解决这个问题 - 因为超类构造函数首先运行。但是,从超类构造函数修改子类字段似乎是错误的。

据说使用单独的init方法,有些事情更简单,更容易维护。另请注意,EJB也会提升@PostConstruct注释。

答案 2 :(得分:1)

我想这个选择是为了简化servlet的编码。在当前情况下,不需要特定初始化的servlet可以这样编码:

public class MyServlet extends HttpServlet {
    // doGet, doPost, etc.
}

如果使用构造函数初始化servlet,则需要对其进行编码:

public class MyServlet extends HttpServlet {

    public MyServlet(ServletConfig config) {
        super(config);
    }

    // doGet, doPost, etc.
}
BTW,他们甚至引入了一种无法初始化的方法,可用于避免被迫调用super.init(config)

答案 3 :(得分:1)

简答:NO。

答案很长: 如果servlet包含构造函数和init方法,您将看到首先调用构造函数,然后调用init方法(使用sysout语句尝试)。

servlet是一个java类,所以它必须遵循java进程,所以首先调用构造函数然后调用init方法(注意你的servlet容器调用init方法就像tomcat一样,因为这就是servlet应该是怎样的初始化;读取servlet规范)。

因此,如果您需要执行一些特定于您的业务需求的操作(例如创建数据库连接或读取一组用户详细信息等);构造函数不是放置这些东西的最佳位置。

通常构造函数不应该有任何复杂的逻辑/业务处理。他们应该初始化最小的成员变量并将复杂的事情留待以后;在servlet的情况下,可以通过init方法完成繁重的工作。

另请注意,在调用init()时,servlet容器已启动并准备好系统资源,即它将初始化JNDi名称绑定,数据源等等。 因此,在某种程度上,它可以保证当您调用init()时,它将为您准备好系统资源。

servlet 3规范说:

  

2.3.1加载和实例化servlet容器负责   用于加载和实例化servlet。加载和实例化   容器启动时可能会发生,或延迟到容器   容器确定服务请求所需的servlet。什么时候   servlet引擎启动后,必须找到所需的servlet类   由servlet容器。 servlet容器加载servlet   使用普通Java类加载工具的类。装载可能是   来自本地文件系统,远程文件系统或其他网络   服务。加载Servlet类后,容器实例化   它可供使用。

     

2.3.2初始化servlet对象实例化后,   容器必须初始化servlet才能处理请求   来自客户。提供初始化以便servlet可以读取   持久配置数据,初始化昂贵的资源(如   基于JDBC API的连接),并执行其他一次性活动。该   容器通过调用init方法初始化servlet实例   Servlet接口的唯一(每个servlet声明)   实现ServletConfig接口的对象。这个配置   object允许servlet访问名称值初始化   Web应用程序的配置信息中的参数。该   配置对象还为servlet提供对象的访问权限   (实现ServletContext接口)描述了   servlet的运行时环境。有关更多信息,请参见第4章Servlet上下文   有关ServletContext接口的信息。

阅读本部分:

The servlet container loads the servlet class using normal Java class loading facilities.

所以,容器必须使用标准的java类加载机制。这意味着它无法做到邓肯刚刚建议的那样。

答案 4 :(得分:0)

int(ServletConfig config)是Servlet的生命周期方法,它由servlet容器调用。

我们可以替换超类servlet的参数构造函数中的init方法代码。 但我们不能强迫开发人员调用超类构造函数 例如

 /*If generic servlet has a constructor like this*/
      public GenericServlet(ServletConfig  config){
        ....
 }

 /*And Developers servlet is calling only default servlet.*/
public MyServlet(){
  super();
}

因此在这种情况下,初始化永远不会发生在该servlet中。它会导致问题。因为ServletConfig obj未初始化。 我们不能强迫用户调用specifict超类构造函数。

答案 5 :(得分:0)

简单的答案是你必须有一个no-arg ctor和一个init方法,因为这是规范所要求的......

为什么这样写的规范可能是历史问题。这些天我认为我们可能推迟构建,直到ServletContext可用,并用该参数调用ctor。但回顾过去有一个ServletContext.getServlet(name)方法,因此一个servlet可以在初始化时查找另一个servlet并与之通信。为了实现这一目标,他们都必须事先创建,然后初始化。

getServlet已被弃用,现在返回null(我认为这是运行多个应用的​​容器的安全漏洞)。

相关问题