如何使用参数启动时初始化Servlet?
我们可以写一个Servlet的参数的构造函数?
是的,你可以,但它是没用的,因为servlet容器不会调用它。
正确的方式做到这一点是使用init()
方法:
@Override
public void init() throws ServletException {
String foo = getInitParameter("foo");
String bar = getServletContext().getInitParameter("bar");
// ...
}
在这个例子中,getInitParameter("foo")
返回web.xml
具体<servlet>
条目的<init-param>
的价值,getServletContext().getInitParameter("bar")
返回的值独立<context-param>
在web.xml
。
构造函数是由应用程序服务器管理的对象。
有关初始化,请参阅init()方法。
更新:
我可以用一个构造函数在我的servlet?
答:一个servlet是一个普通的Java类,所以当没有自定义 构造函数时,默认的构造函数是没有参数的。 Servlet容器通常使用 Class.newInstance()方法加载 servlet,所以你必须小心 添加一个显式的默认构造函数,如果你添加了非默认的构造函数,则为 。
为什么init()而不是servlet的构造函数? – 2009-08-14 04:48:29
你不能。 Servlet由容器反射性地实例化。如果Servlet规范已经允许在构造函数的参数,你就必须有一些复杂的部署描述符一样,
<servlet>
<servlet-name>MyServlet</servlet-name>
<servlet-class>MyServlet</servlet-class>
<servlet-argument id="1" type="string">Test<servlet-argument>
<servlet-argument id="2" type="int">10</servlet-argument>
<load-on-startup>1</load-on-startup>
</servlet>
我想没有人希望这样。
有趣的答案 – 2009-08-14 05:02:33
这里的问题是servlet配置语法,而不是参数化构造函数的复杂性 – Aivar 2011-10-29 14:05:21
问题可能状态更一般。
“根据servlet的(2.3) 规范中,Servlet是 由servlet引擎实例化由 调用无参数的构造如何 能我初始化一个servlet正确 因为正确初始化 依赖于 中心/国际/独特/应用 配置?”
实际上,你可以在构造函数中使用serlvets和/或根据你的喜好初始化它们。但是,它需要一点管道。
假设你有一个有构造函数参数的一个servlet:
package org.gawi.example.servlets;
import java.io.*;
import javax.servlet.*;
import javax.servlet.http.*;
public class SampleServlet extends HttpServlet
{
private final String mMessage;
public SampleServlet(String message)
{
mMessage = message;
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException
{
response.setContentType("text/plain");
response.getWriter().write(mMessage);
}
}
你首先需要的是一种独特的servlet whithin您的应用程序,让我们称之为InitializationServlet,创建所有需要的实例。然后必须将这些实例导出到servlet上下文中以供其他servlet检索(稍后解释)。该InitializationServlet可能是这样的:
package org.gawi.example.servlets;
import javax.servlet.*;
import javax.servlet.http.*;
public class InitializationServlet extends HttpServlet
{
public void init() throws ServletException
{
SampleServlet servletA = new SampleServlet("this is servlet A");
SampleServlet servletB = new SampleServlet("this is servlet B");
SampleServlet servletC = new SampleServlet("this is servlet C");
getServletContext().setAttribute("servletA", servletA);
getServletContext().setAttribute("servletB", servletB);
getServletContext().setAttribute("servletC", servletC);
}
}
你看到只有init()
方法已经提供。此servlet不处理任何HTTP请求。它的唯一目的是将Servlet存储在ServletContext中。请注意,您也可以使用此servlet来加载您的应用程序配置。因此,这可以充当网络应用程序入口点,如程序的main(String[] args)
方法。这可能会提醒你SpringSource的ContextLoaderServlet。
的最后一块是将有效地由servlet容器实例化的DelegateServlet,只有这个servlet会将所有相关的方法调用被包装的servlet实例:
package org.gawi.example.servlets;
import java.io.*;
import javax.servlet.*;
import javax.servlet.http.*;
public class DelegateHttpServlet extends HttpServlet
{
private static final String SERVLET_CONTEXT_KEY_INIT_PARAMETER = "servletContextKey";
private HttpServlet mServlet;
public void init(ServletConfig servletConfig) throws ServletException
{
super.init(servletConfig);
locateServlet(servletConfig);
mServlet.init(servletConfig);
}
private void locateServlet(ServletConfig servletConfig) throws ServletException
{
String servletContextAttributeName = servletConfig.getInitParameter(SERVLET_CONTEXT_KEY_INIT_PARAMETER);
if (servletContextAttributeName == null)
{
throw new ServletException("Unable to find init parameter '" + SERVLET_CONTEXT_KEY_INIT_PARAMETER + "'");
}
Object object = servletConfig.getServletContext().getAttribute(servletContextAttributeName);
if (object == null)
{
throw new ServletException("Unable to find " + servletContextAttributeName + " in servlet context.");
}
if (!(object instanceof HttpServlet))
{
throw new ServletException("Object is not an instance of"
+ HttpServlet.class.getName()
+ ". Class is "
+ object.getClass().getName()
+ ".");
}
mServlet = (HttpServlet) object;
}
public void destroy()
{
mServlet.destroy();
}
public void service(ServletRequest req, ServletResponse res) throws ServletException, IOException
{
mServlet.service(req, res);
}
}
在其初始化时,DelegateServlet会使用servlet初始参数在servlet上下文中查找目标servlet。
对于这样的应用程序可能看起来像在web.xml中:
<?xml version="1.0" encoding="ISO-8859-1"?>
<!DOCTYPE web-app
PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
"http://java.sun.com/dtd/web-app_2_3.dtd">
<web-app>
<display-name>Example</display-name>
<description>Example web showing handling of servlets w/ constructors.</description>
<servlet>
<servlet-name>Initialization</servlet-name>
<servlet-class>org.gawi.example.servlets.InitializationServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet>
<servlet-name>A</servlet-name>
<servlet-class>org.gawi.example.servlets.DelegateHttpServlet</servlet-class>
<init-param>
<param-name>servletContextKey</param-name>
<param-value>servletA</param-value>
</init-param>
<load-on-startup>2</load-on-startup>
</servlet>
<servlet>
<servlet-name>B</servlet-name>
<servlet-class>org.gawi.example.servlets.DelegateHttpServlet</servlet-class>
<init-param>
<param-name>servletContextKey</param-name>
<param-value>servletB</param-value>
</init-param>
<load-on-startup>3</load-on-startup>
</servlet>
<servlet>
<servlet-name>C</servlet-name>
<servlet-class>org.gawi.example.servlets.DelegateHttpServlet</servlet-class>
<init-param>
<param-name>servletContextKey</param-name>
<param-value>servletC</param-value>
</init-param>
<load-on-startup>4</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>A</servlet-name>
<url-pattern>/servlet/a</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>B</servlet-name>
<url-pattern>/servlet/b</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>C</servlet-name>
<url-pattern>/servlet/c</url-pattern>
</servlet-mapping>
<session-config>
<session-timeout>5</session-timeout>
</session-config>
</web-app>
请务必先加载InitializationServlet,使用低<load-on-startup>
值。
这种方法的好处是HttpServlet
对象可以像任何其他常规Java对象或bean一样处理。因此,它提供了对初始化的更好控制:在init()
方法中没有更多棘手的事情要做,也没有混乱的servlet init-arg处理。
如果我们有参数化的构造函数或公共构造函数,servlet如何可以是单例? ? servlet容器是否有一个“SampleServlet”的例子,如你的例子。你能否详细说明一下。? – 2014-09-16 08:11:04
servlet + web.xml是历史上第一个依赖注入框架 – dfa 2009-08-14 04:55:42