我们可以将init方法替换为servlet构造函数吗?
我的问题是为什么servlet需要一个单独的方法int(ServletConfig config)
用于初始化,我们可以通过让参数化构造函数let XServlet(ServletConfig config)
来实现相同的东西,并且容器可以调用它。
答案 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(我认为这是运行多个应用的容器的安全漏洞)。