2011年12月20日火曜日

Slim3ソースコード読書会の前に

12/21(水)にSlim3ソースコード読書会(1)を開催する予定なのですが、
思ったより参加者が多いので、それなりに前提知識を整理したいと思います。

第1回はFrontControllerから各Controllerへの処理の振り分け部分について
読んでいく予定ですが、まずjavax.servlet.Filterインターフェイスの認識がないと
だめだと思ったのでその辺りの挙動をまとめておきます。

まず、Slim3でも(Blankプロジェクトのweb.xmlに定義)3つのFilterが定義されています。

    <filter-mapping>
        <filter-name>HotReloadingFilter</filter-name>
        <url-pattern>/*</url-pattern>
        <dispatcher>REQUEST</dispatcher>
    </filter-mapping>  
    <filter-mapping>
        <filter-name>DatastoreFilter</filter-name>
        <url-pattern>/*</url-pattern>
        <dispatcher>REQUEST</dispatcher>
    </filter-mapping>
    <filter-mapping>
        <filter-name>FrontController</filter-name>
        <url-pattern>/*</url-pattern>
        <dispatcher>REQUEST</dispatcher>
        <dispatcher>FORWARD</dispatcher>
        <dispatcher>INCLUDE</dispatcher>
        <dispatcher>ERROR</dispatcher>
    </filter-mapping>
第1回は名前の通りのFrontControllerから読み進めてどのようにControllerの振り分けを
行っているかを確認していこうと考えています。
処理の順番としては、<filter-mapping>タグが付いている順番にFilterインターフェイスが呼び出されます。今回のケースだと、
  1. HotReloadingFilter
  2. DatastoreFilter
  3. FrontController
が呼び出し順になります。したがって、<filter-mapping>の順番を入れ替えると呼び出し順も逆転します。

その挙動を確認するプログラムは、どこかにおく…必要もないと思うので、抜粋します。
3つぐらいFilterを作って設定すれば動作可能だと思います。

public class FirstFilter implements Filter {

 @Override
 public void destroy() {
  // TODO Auto-generated method stub

 }

 @Override
 public void doFilter(ServletRequest req, ServletResponse res,
   FilterChain chain) throws IOException, ServletException {
  System.out.println("FirstFilter#doFilter");
  chain.doFilter(req, res);
 }

 @Override
 public void init(FilterConfig arg0) throws ServletException {
  // TODO Auto-generated method stub

 }

}

Filterインターフェイスは3つのメソッドを実装し、以下のタイミングで呼び出されます。
  • init():フィルタの初期化時(1度だけ呼び出される)
  • doFilter():web.xmlの<filter-mapping>タグで設定したリクエスト時
  • destroy():コンテナが破棄される時などフィルタが破棄されるタイミング
Slim3では、doFilter()を駆使してコントローラの振り分けを行っているようです。

また、doFilterの引数であるFilterChain#doFilter(req, res)を呼び出さないと、
以降のFilterが実行されなくなるので、サーブレット/JSPを実行する場合も
注意が必要です。(動作を確認する場合は、chain.doFilter()をコメントアウトして下さい。)

以下、参考にしたサイト

Javaの道(Servlet-10.フィルタ)
http://www.javaroad.jp/servletjsp/sj_servlet10.htm

tomcatのドキュメント(Filterインターフェイス)
http://tomcat.apache.org/tomcat-5.5-doc/servletapi/javax/servlet/Filter.html

Tomcatでフィルタを使う
http://www.nina.jp/server/slackware/webapp/tomcat_filter.html