web-dev-qa-db-ja.com

起動時にパラメータを使用してサーブレットを初期化するにはどうすればよいですか?

サーブレットに引数コンストラクターを書くことはできますか?はいの場合、どのように電話できますか?

21
Biju CD

サーブレットに引数コンストラクターを記述できますか?

はい、できますが、サーブレットコンテナが呼び出さないため、役に立ちません。

それを行う適切な方法は、 init() メソッドを使用することです。

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

この例では、 getInitParameter("foo") は、_<init-param>_の特定の_<servlet>_エントリの_web.xml_の値を返します。 getServletContext().getInitParameter("bar") _<context-param>_の独立した_web.xml_の値を返します。

29
dfa

問題は、より一般的に述べることができます。

「サーブレット(2.3)仕様によると、サーブレットは引数なしのコンストラクターを呼び出すことにより、サーブレットエンジンによってインスタンス化されます。正しい初期化が中央/グローバル/一意/アプリケーションの構成に依存する場合、サーブレットを適切に初期化するにはどうすればよいですか?

実際には、コンストラクターでセルベットを使用したり、必要に応じて初期化したりすることができます。ただし、少し配管が必要です。

引数を持つコンストラクターを持つサーブレットがあると仮定します。

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

最初に必要なのは、アプリケーション内の一意のサーブレットです。これをInitializationServletと呼び、必要なすべてのインスタンスを作成します。次に、これらのインスタンスをサーブレットコンテキストにエクスポートして、別のサーブレットで取得する必要があります(後で説明します)。 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()メソッドのみが提供されていることがわかります。このサーブレットはHTTPリクエストを処理していません。その唯一の目的は、サーブレットをServletContextに格納することです。このサーブレットを使用してアプリケーション構成をロードすることもできることに注意してください。したがって、これは、プログラムのmain(String[] args)メソッドのように、Webアプリケーションのエントリポイントとして機能できます。これは、SpringSourceのContextLoaderServletを思い出させるかもしれません。

最後の部分は、サーブレットコンテナによって効果的にインスタンス化されるDelegateServletです。このサーブレットだけが、関連するすべてのメソッド呼び出しをラップされたサーブレットインスタンスに転送します。

_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は、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>
_

必ず最初に、低い_<load-on-startup>_値を使用してInitializationServletをロードしてください。

このアプローチの利点は、HttpServletオブジェクトを他の通常のJavaオブジェクトまたはBeanと同じように処理できることです。したがって、初期化をより適切に制御できます。 init()メソッドでも、厄介なサーブレットのinit-arg処理でも実行できます。

24
gawi

できません。サーブレットは、コンテナによって反射的にインスタンス化されます。サーブレット仕様でコンストラクターで引数が許可されている場合は、次のような複雑なデプロイメント記述子が必要になります。

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

私は誰もそれを望んでいないと思います。

6
ZZ Coder

コンストラクターは、アプリケーションサーバーによって管理されるオブジェクトです。

初期化については、 init() メソッドを参照してください。

更新:

サーブレットでコンストラクターを使用できますか?

A:サーブレットは通常のJavaクラスであるため、カスタムコンストラクタがない場合、引数のない暗黙のデフォルトコンストラクタがあります。サーブレットコンテナは通常、Class.newInstance()メソッドを使用してロードします。サーブレットなので、デフォルト以外のコンストラクターを追加する場合は、明示的なデフォルトコンストラクターを追加するように注意する必要があります。

ソース: http://www.codestyle.org/Java/servlets/FAQ.shtml

5
Tom