2009-08-14 16 views

Respuesta

25

Podemos escribir un constructor sin argumentos en un servlet?

Sí, puede hacerlo, pero es inútil ya que el contenedor de servlets no lo invocará.

La manera apropiada de hacerlo es utilizar la init() método:

@Override 
public void init() throws ServletException { 
    String foo = getInitParameter("foo"); 
    String bar = getServletContext().getInitParameter("bar"); 
    // ... 
} 

En este ejemplo getInitParameter("foo"), devuelve el valor de la <init-param> de la <servlet> entrada específica en web.xml, y getServletContext().getInitParameter("bar") devuelve el valor de la independiente <context-param> en web.xml.

+3

servlet + Web.xml fue uno de los primeros marco de inyección de dependencias de la historia – dfa

5

Los constructores son objetos gestionados por el servidor de aplicaciones.

Para la inicialización, consulte el método init().

Actualización:

¿Puedo usar un constructor en mi servlet?

A: Un servlet es una clase Java normal, por lo que cuando no hay constructores personalizados , hay un constructor predeterminado implícito sin argumentos. Los contenedores de servlets suelen utilizar el método Class.newInstance() para cargar los servlets , por lo que debe tener cuidado al agregar un constructor predeterminado explícito si agrega constructores no predeterminados.

fuente: http://www.codestyle.org/java/servlets/FAQ.shtml

+0

¿Por qué init() en lugar del constructor de servlet? –

5

No puede. El servlet se instancia de forma reflexiva por contenedor. Si especificación servlet han permitido a los argumentos de constructor, que tendría que tener algún descriptor de despliegue complicada como,

<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> 

Creo que nadie quiere eso.

+0

Interesante respuesta –

+1

El problema aquí es la sintaxis de configuración del servlet, no complejidad de constructores parametrizados – Aivar

20

El problema puede ser el estado más genéricamente:.

"De acuerdo con los servlets (2.3) memoria descriptiva, los servlets son instancia por el motor servlet invocando la no-arg constructor Cómo puede Inicializo un servlet correctamente dado que la inicialización correcta depende de la configuración central/global/única/aplicación ? "

En realidad, puede usar serlvets con constructor y/o inicializarlos como desee. Sin embargo, requiere un poco de plomería.

suponiendo que tiene un servlet con un constructor que tiene argumentos:

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); 
    } 
} 

Lo primero que se necesita es un servlet única whithin su solicitud, vamos a llamarlo InitializationServlet, para crear todos los casos requeridos. Esas instancias deben luego exportarse en el contexto del servlet para ser recuperadas por otro servlet (explicado más adelante). El InitializationServlet puede tener este aspecto:

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); 
    } 
} 

se ve que sólo el método init() se ha proporcionado. Este servlet no está atendiendo ninguna solicitud HTTP. Su único propósito es almacenar el servlet en el ServletContext. Tenga en cuenta que también podría haber usado este servlet para cargar la configuración de su aplicación. De modo que puede actuar como punto de entrada de la aplicación web, como el método main(String[] args) de un programa. Esto podría recordarle el ContextLoaderServlet de SpringSource.

La última pieza es la DelegateServlet que efectivamente se crea una instancia por el contenedor servlet, sólo que esta servlet se transmita toda el método pertinente llama a la instancia de servlet envuelto:

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); 
    } 

} 

Durante su inicialización, el DelegateServlet voluntad busca el servlet objetivo en el contexto del servlet usando el argumento inicial del servlet servletContextKey.

El web.xml para una aplicación de este tipo podría parecerse a lo siguiente:

<?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> 

Asegúrese de cargar la InitializationServlet primer lugar, utilizando un valor bajo <load-on-startup>.

El beneficio de este enfoque es que los objetos HttpServlet se pueden manejar como cualquier otro objeto o bean Java regular. Por lo tanto, proporciona un mejor control sobre la inicialización: no hay más cosas difíciles de hacer en el método init(), ni el manejo del servlet init-arg.

+0

¿Cómo pueden ser servlets Singleton si hemos parametrizado constructor o un constructor público? ? El contenedor de servlets tendrá un solo instance de "SampleServlet" como en su ejemplo. ¿Puedes por favor elaborar? –

Cuestiones relacionadas