NetBeans 6.7RCで先取り Servlet 3.0の動的サーブレット登録

サーブレット3.0ではサーブレットやフィルタを動的に登録することができます。コードを見てもらえればすぐにわかると思いますので、まずはさくっとコードをのせます。

これがサーブレットリスナーのコードすべてです。省略なし!web.xmlはからっぽです。ファイル自体削除してもかまいません。

package listener;

import java.util.logging.Level;
import java.util.logging.Logger;
import javax.servlet.ServletContext;
import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;
import javax.servlet.ServletException;
import javax.servlet.ServletRegistration;
import javax.servlet.annotation.WebListener;
import servlet.HogeServlet;

/**
 * Web application lifecycle listener.
 * @author shin
 */
@WebListener
public class NewServletListener implements ServletContextListener {

    @Override
    public void contextInitialized(ServletContextEvent sce) {
        System.out.println("サーブレット登録しますよ");
        try {
            ServletContext sc = sce.getServletContext();

            //クラスで登録
            sc.addServlet("hogeServlet", HogeServlet.class);

            //インスタンスで登録
            HogeServlet hogeServlet = sc.createServlet(HogeServlet.class);
            sc.addServlet("hogeServlet1", hogeServlet);

            //クラス名で登録
            sc.addServlet("hogeServlet2", "servlet.HogeServlet");


            //ここからはマッピング
            ServletRegistration hoge = sc.findServletRegistration("hogeServlet");
            hoge.addMapping("/hoge");

            ServletRegistration hoge1 = sc.findServletRegistration("hogeServlet1");
            hoge1.addMapping("/hoge1","/hoge1/*");//カンマ区切りでいくらでも

            ServletRegistration hoge2 = sc.findServletRegistration("hogeServlet2");
            hoge2.addMapping("/hoge2","/hoge2/*");

            System.out.println("サーブレット登録完了");
        } catch (ServletException ex) {
            Logger.getLogger(NewServletListener.class.getName()).log(Level.SEVERE, null, ex);
        }
    }

    @Override
    public void contextDestroyed(ServletContextEvent sce) {
    }
}

見てわかるとおり、まずクラスの上に「@WebListener」アノテーションがついています。これがついているだけで起動時に読み込まれます。

ServletContext#addServletメソッドがサーブレットを登録します。
ServletRegistrationで登録したサーブレットをどのURLにマッピングするかを可変長引数で記述することができます。

上記のコードではhoge2サーブレットは以下のどのURLでも呼ばれます。

  • /hoge2
  • /hoge2/a
  • /hoge2/a/b/c/d

フレームワークの場合は「/*」のようなかんじでよいですね。その上で静的ファイルは除外するようにしたほうがよいかと思われます。



今回はサーブレットだけやりましたがフィルタも同様です。

メソッド等は以下のURLを参考にしてください
http://java.sun.com/javaee/6/docs/api/javax/servlet/ServletContext.html

サーブレットやフィルタのcreateメソッドがあるのが不思議に思えるかもしれません。自分でnewしてもよさそうなのに。これはJavaEE 5からサーブレットはインジェクト用のアノテーションがあれば適切に注入されるようにする必要があるからです。注入はTomcatでいえば6から対応しています。それらのフィールドインジェクション(セッターもあったかな?)をしてくれるのです。これはちょうどDIコンテナに生成してもらうのとにたようなものです。本当はここに最近JCPに登録されたJSR330(javax.inject or java.injectパッケージ)があれば汎用的にできるんですけどね。

ポイントとしてはインスタンスの生成方法は強要していません。ですから好きなものをここに入れることが可能です。



サーブレット3.0ではライブラリに登録されているクラスも探し出して登録します。つまり、warアーカイブならばWEB-INF/libフォルダに上記クラス(とサーブレット)が入ったjarを置くだけでweb.xmlに何も設定せずに自動でサーブレットやフィルタが登録されるのです。

これが一番すごいところで、JavaEE 6時代のフレームワークのセットアップはWEB-INF/libフォルダにjarファイルを置くだけということになります。デフォルトのマッピングならば環境設定なし、環境設定ファイルを用意したりサービスローダーを使えばカスタマイズしたマッピングが可能というのが常識になるはずです。

あなたはまだこれでもアンチJavaEE派ですか?なんちて。