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

2022-09-02 00:10:31

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


答案 1

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

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

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

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

在此示例中,getInitParameter(“foo”) 返回 中特定条目的值,getServletContext().getInitParameter(“bar”) 返回 中独立项的值。<init-param><servlet>web.xml<context-param>web.xml


答案 2

问题可以更笼统地陈述:

“根据 servlets (2.3) 规范,servlet 由 servlet 引擎通过调用 no-arg 构造函数来实例化。如果正确的初始化取决于中心/全局/唯一/应用程序配置,我如何正确初始化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,我们称之为初始化Servlet,以创建所有必需的实例。然后,必须在 servlet 上下文中导出这些实例,以便由另一个 servlet 检索(稍后将解释)。初始化服务包可能如下所示:

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

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

最后一部分是 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);
    }

}

在初始化期间,DelegateServlet 将使用 servlet 初始参数在 servlet 上下文中查找目标 servlet。servletContextKey

此类应用程序的 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>

请确保首先使用较低的值加载初始化Servlet。<load-on-startup>

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