Locked History Actions

guice/Manual/Integration/WebandServlets/ServletModule

サーブレットモジュールのインストール

GuiceFilterを設定して起動すればGuiceサーブレットがセットアップされるが、 しかしGuiceサーブレットを実際に使うためにはServletModuleインスタンスのインストールが必要である。

   Guice.createInjector(new ServletModule());

このモジュールはリクエスト及びセッションスコープをセットアップし、フィルターとサーブレットをコンフィギュレーションするための方法を提供する。 インジェクタを作成する場所はいかなるところでも構わないのだが、論理的な場所としてServletContextListenerがある。

ServletContextListenerはウェブアプリケーションが配備された直後、リクエストが到着する以前にトリガーされるJavaサーブレットである。 Guiceサーブレットはサブクラス化するための便利なユーティリティを提供しているの、あなた自身のServletContextListenerを作成することができる。

public class MyGuiceServletConfig extends GuiceServletContextListener {

  @Override
  protected Injector getInjector() {
    return Guice.createInjector(new ServletModule());
  }
}

次に、以下のようなweb.xmlを追加し、サーブレットコンテナがアプリケーション配備時にこのクラスをトリガーできるようにする。

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

これで、必要に応じてGuiceサーブレットを使えるようになった。 ただし、必ずしもGuiceサーブっトを使うために、ServletContextListenerは必要ではない、 インジェクタ生成時にServletModuleのインストールを忘れさえしなければ。

バインディング言語

ServletModuleをweb.xml配備デスクリプタのコードによる置き換えと考えてみよう。 フィルタとサーブレットは通常のJavaメソッド呼び出しによってコンフィギュレーションされる。 以下はGuiceインジェクタを作成する際にサーブレットを登録する典型的な例である。

   Guice.createInjector(..., new ServletModule() {

     @Override
     protected void configureServlets() {
       serve("*.html").with(MyServlet.class)
     }
   }

これは.htmlで終了するすべてのウェブリクエストをサービスするためのMyServletという名のサーブレット(HttpServletのサブクラス)を登録するものである。web.xmlと同様にパススタイルのサーブレット登録も可能である。

       serve("/my/*").with(MyServlet.class)

フィルタマッピング

サーブレットフィルタを同様のシンタックスでマップすることができる。

      filter("/*").through(MyFilter.class);

これはMyFilterを通して到着するすべてのリクエストをルーティングし、 他のマッチするフィルタを通し、最終的に処理サーブレットに配布する。

注意:すべてのサーブレット(あるいはフィルタ)は@Singletonでなければならない。 もしこれらのクラスに直接的にアノテーションできない場合は、bind(..).in(Singleton.class)でバインドすること、 separate to the filter() or servlet() rules. 他のスコープへのマッピングはエラーとなる。 これはサーブレット仕様の一貫性保持のためである。 Guiceサーブレットは古いSingleThreadModelはサポートしていない。

提供される注入

サーブレットモジュールをインストールすることにより、サーブレットフレームワークから様々なクラスにアクセスが可能となる。 ServletModuleをインストールすると、サーブレットプログラミングモデルで便利なものが得られるし、デフォルトでGuiceが注入するオブジェクトが得られる。

/** 訳注:サーブレットでは無いPOJO(Plain Old Java Object)に注入する例 */
@RequestScoped
class SomeNonServletPojo {

  @Inject
  public SomeNonServletPojo(HttpServletRequest request, HttpServletResponse response, HttpSession session) {
    ...
  }

}

リクエストとレスポンスは現在のhttpリクエストにスコープされる。 同様に、httpセッションオブジェクトは現在のユーザセッションにスコープされる。 これに加え、現在のServletContextを注入することができるし、@RequstParametersバインディングアノテーションを用いてリクエストパラメータマップを注入することもできる。

@Inject @RequestParameters Map<String, String[]> params;

これは文字列を文字列配列にマップする、httpは一つのリクエストパラメータに複数の値を許すからだが、典型的には一つの値だけである。 ただし、リクエストあるいはセッションスコープにクラスに、シングルトンあるいはより広いスコープのインスタンスからアクセスしたい場合は、Provider<T>を使うべきである。

ディスパッチの順序

このようにすきなだけサーブレットやフィルタを登録することができる。 これらはServletModuleに現れた順序で比較されディスパッチされる。

   Guice.createInjector(..., new ServletModule() {

     @Override
     protected void configureServlets() {
       filter("/*").through(MyFilter.class);
       filter("*.css").through(MyCssFilter.class);
       // etc..

       serve("*.html").with(MyServlet.class);
       serve("/my/*").with(MyServlet.class);
       // etc..
      }
    }

これらは、リストを語彙順で検索される。例えば、 「/my/files.js」というURLは、以下のサーブレットマッピングより先に比較される。

       serve("*.html").with(MyServlet.class);

失敗した場合は、次のサーブレットマッピングに降りる。

       serve("/my/*").with(MyServlet.class);

このルールはマッチするので、GuiceサーブレットはリクエストをMyServletにディスパッチし、マッチング処理を終了する。

同様の処理がフィルタの順序ディスパッチにも適用される (つまり、バインディングリストに現れた順である)。

可変引数のマッピング

上の二つのマッピングルールは可変引数シンタックスを使って、コンパクトに記述することができる。

       serve("*.html", "/my/*").with(MyServlet.class);

このように様々なURIパターンを一つサーブレットでマップ可能である。 同様のシンタックスがフィルタマッピングでも使用できる。