如何使用参数启动时初始化Servlet?

问题描述:

我们可以在Servlet中写一个参数构造函数吗?如果是的话,你怎么打电话?如何使用参数启动时初始化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

+3

servlet + web.xml是历史上第一个依赖注入框架 – dfa 2009-08-14 04:55:42

构造函数是由应用程序服务器管理的对象。

有关初始化,请参阅init()方法。

更新:

我可以用一个构造函数在我的servlet?

答:一个servlet是一个普通的Java类,所以当没有自定义 构造函数时,默认的构造函数是没有参数的。 Servlet容器通常使用 Class.newInstance()方法加载 servlet,所以你必须小心 添加一个显式的默认构造函数,如果你添加了非默认的构造函数,则为 。

来源:http://www.codestyle.org/java/servlets/FAQ.shtml

+0

为什么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> 

我想没有人希望这样。

+0

有趣的答案 – 2009-08-14 05:02:33

+1

这里的问题是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处理。

+0

如果我们有参数化的构造函数或公共构造函数,servlet如何可以是单例? ? servlet容器是否有一个“SampleServlet”的例子,如你的例子。你能否详细说明一下。? – 2014-09-16 08:11:04