web-dev-qa-db-ja.com

特別な自動開始サーブレットを使用して起動時に初期化し、アプリケーションデータを共有する

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

アプリケーションをセットアップする2つの方法がわかります。

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

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

32
riz

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


CDI/JSF/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をまだ使用しておらず、アップグレードできないために_@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");
        // ...
    }
_

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


CDIは利用できますか? _@Observes_ on _ApplicationScoped.class_ を使用します

_import javax.enterprise.context.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_を介して利用できます。必要に応じて_@Named_も作成して、ELの_#{config}_からも利用できるようにします。

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


JSFは利用できますか? @ManagedBean(eager=true) を使用します

_import javax.faces.bean.ManagedBean
import javax.faces.bean.ApplicationScoped;

@ManagedBean(eager=true)
@ApplicationScoped
public class Config {

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

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

これは、ELの_#{config}_からも利用できます。


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_を介して利用できます。スタートアップフックのためにEJBを悪用してはならないので、私は「検討する」と言っています。さらに、_@Singleton_はデフォルトで読み取り/書き込みロックされており、主にバックグラウンドジョブのスケジューリングなどのトランザクション関連のものを対象としています。

参照:

74
BalusC