2009-08-14 70 views

回答

25

我們可以寫一個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

5

構造函數是由應用程序服務器管理的對象。

有關初始化,請參閱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

5

你不能。 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

20

問題可能狀態更一般。

「根據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