如何使用参数在启动期间初始化Servlet?

Bij*_* CD 21 java servlets initialization

我们可以在Servlet中编写参数构造函数吗?如果是的话,你怎么打电话?

dfa*_*dfa 28

我们可以在Servlet中编写参数构造函数吗?

是的,你可以,但它没用,因为servlet容器不会调用它.

正确的方法是使用以下init()方法:

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

在这个例子中,getInitParameter("foo")返回的值<init-param>的具体的<servlet>在条目web.xml,并且getServletContext().getInitParameter("bar")返回独立的值<context-param>web.xml.

  • servlet + web.xml是历史上第一个依赖注入框架之一 (3认同)

gaw*_*awi 24

问题可能是更普遍的状态:

"根据servlets(2.3)规范,servlet通过调用no-arg构造函数来实例化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);
    }
}
Run Code Online (Sandbox Code Playgroud)

您需要的第一件事是在您的应用程序中使用一个独特的servlet,我们称之为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);
    }
}
Run Code Online (Sandbox Code Playgroud)

您看到只提供了init()方法.此servlet不为任何HTTP请求提供服务.它的唯一目的是将servlet存储在ServletContext中.请注意,您也可以使用此servlet加载应用程序配置.因此,这可以充当Web应用程序入口点,就像main(String[] args)程序的方法一样.这可能会提醒您SpringSource的ContextLoaderServlet.

最后一部分是DelegateServlet,它将由servlet容器实际实例化,只有这个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);
    }

}
Run Code Online (Sandbox Code Playgroud)

在初始化期间,DelegateServlet将使用servletContextKeyservlet初始参数在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>
Run Code Online (Sandbox Code Playgroud)

请务必先使用较低的<load-on-startup>值加载InitializationServlet .

这种方法的好处是HttpServlet可以像处理任何其他常规Java对象或bean一样处理对象.因此,它提供了对初始化的更好控制:在init()方法中没有更多棘手的事情,也没有凌乱的servlet init-arg处理.


ZZ *_*der 6

你不能.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>
Run Code Online (Sandbox Code Playgroud)

我猜没有人想要那个.


Tom*_*Tom 5

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

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

更新:

我可以在servlet中使用构造函数吗?

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

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