34

いくつかの構成を取得し、どこかの外部リソース/オブジェクト/システムに接続して、アプリケーション スコープに保存する必要があります。

アプリケーションをセットアップするには、次の 2 つの方法があります。

  • init()既存のサーブレットと必要なコードをオーバーライドし、構築されたすべてのオブジェクトを同じサーブレット内に保持します。
  • ある種の初期化サーブレットを用意し、それを使用しinit()て作業を行います。次に、作成したオブジェクトを に保存ServletContextして、他のサーブレットと共有します。

上記のうち、どれがより良いアプローチですか?サーブレット間でオブジェクトを共有するより良い方法はありますか? お互いに直接呼び出したり…?

4

1 に答える 1

85

どちらも優れたアプローチではありません。サーブレットは、デプロイ イベント (起動/シャットダウン) ではなく、HTTP イベント (HTTP 要求) をリッスンすることを目的としています。


CDI/EJB が利用できない? 使用するServletContextListener

@WebListener
public class Config implements ServletContextListener {

    public void contextInitialized(ServletContextEvent event) {
        // Do stuff during webapp's startup.
    }

    public void contextDestroyed(ServletContextEvent event) {
        // Do stuff during webapp's shutdown.
    }

}

まだサーブレット 3.0 を使用しておらず、アップグレードできず (サーブレット 3.0 は 10 年以上前に導入されたので、そろそろ時期です)、アノテーションを使用できない場合は、以下@WebListenerのように手動で登録する必要があります。 /WEB-INF/web.xml:

<listener>
    <listener-class>com.example.Config</listener-class>
</listener>

(すべてのサーブレットがオブジェクトにアクセスできるように) アプリケーション スコープでオブジェクトを格納および取得するには、 と を使用ServletContext#setAttribute()#getAttribute()ます。

リスナーが自分自身をアプリケーション スコープに格納できるようにする例を次に示します。

    public void contextInitialized(ServletContextEvent event) {
        event.getServletContext().setAttribute("config", this);
        // ...
    }

次に、サーブレットで取得します。

    protected void doGet(HttpServletRequest request, HttpServletResponse response) {
        Config config = (Config) getServletContext().getAttribute("config");
        // ...
    }

によって JSP EL でも利用できます${config}。したがって、単純な Bean にすることもできます。


CDI利用可能? 使用@ObservesするApplicationScoped.class

import jakarta.enterprise.context.ApplicationScoped; // And thus NOT e.g. jakarta.faces.bean.ApplicationScoped

@ApplicationScoped
public class Config {

    public void init(@Observes @Initialized(ApplicationScoped.class) ServletContext context) {
        // Do stuff during webapp's startup.
    }

    public void destroy(@Observes @Destroyed(ApplicationScoped.class) ServletContext context) {
        // Do stuff during webapp's shutdown.
    }
}

これは、 を介してサーブレットで利用できます@Inject。必要に応じて作成し、EL でも@Named使用できるようにします。#{config}

これは CDI 1.1 以降の新機能であることに注意してください。まだ CDI 1.0 を使用していてアップグレードできない場合は、別の方法を選択してください。

Tomcat などの非 JEE サーバーに CDI をインストールする方法に興味がある場合は、Tomcat にCDI をインストールして使用する方法を参照してください。


EJB は利用できますか? 検討@Startup@Singleton

@Startup
@Singleton
public class Config {

    @PostConstruct
    public void init() {
        // Do stuff during webapp's startup.
    }

    @PreDestroy
    public void destroy() {
        // Do stuff during webapp's shutdown.
    }
}

これは、 を介してサーブレットで利用できます@EJB。他のアプローチとの違いは、デフォルトでトランザクション対応であり、@Singleton読み取り/書き込みもロックされていることです。したがって、ランダムな EJB (例: @Stateless) を@WebListenerまたはに注入する必要がある@ApplicationScoped場合は、基本的に両方を単一の にマージすることができます@Startup @Singleton

以下も参照してください。

于 2010-08-12T13:46:38.660 に答える