Chapter 5 : Container
Request,Responseを受け取ってからの処理はContainerによって行われます。ContainerはContainerを自分の子供として持つことが出来ます。
インターフェースContainerのサブインターフェースはEngine, Host, Context, Wrapperの4種です。server.xmlで見慣れたやつらですね。
- Engine
- Tomcat本体。Hostを持つ
- Host
- ひとつのVirtual Hostを表す。Contextを持つ
- Context
- ひとつのWebアプリを表す。Wrapperを持つ
- Wrapper
- ひとつのServletを表す
実はTomcatの中には、この4つのインターフェースの実装クラスはひとつずつ、StandardEngine, StandardHost, StandardContext, StandardWrapperがあるだけです。インターフェース上では明確な関連は無いのですが、実装クラスではContainer.addChild(Container)メソッドが呼ばれた際、引数を型チェックして自分の子供にふさわしくない型の場合はエラーにします。結果的に階層的に子Containerを保持することになり、Engine→Host→Context→Wrapperという構造が出来上がります。
この章ではContainerの共通機能を勉強します(個々のContainerは後の章で解説されます)。
Containerが関連するクラス(インターフェース)としてLogger, Loader, Pipeline, Manager, Realmなどがあります。このなかではPipelineがくせものです。
とりあえずPipelineが何かっていうと Chain Of Responsibility です。
14.Chain of Responsibility パターン | TECHSCORE(テックスコア)
もう「Pipeline」=「Interceptor」=「Filter」=「Chain Of Responsibility」でいいですよね?!細かい定義の違いとかがあったら勘弁してください*1。で、Pipelineクラス自体は Chain Of Responsibility でいうClientの役割です。Handlerに相当するのはValveクラスです。これはserver.xmlに書かれたりするので見覚えのある方もいるでしょう。Containerに登録されたValveたちをPipelineが管理し、Valveの連鎖をRequestがくぐり抜けていく・・・と考えるとスッキリするんですが(そしてそう考えても困らない)、、、
もうひとり登場人物がいました。ValveContextです。ValveContextは「Valveたちを順番に呼び出す」役割を担っています。ValveのinvokeメソッドはRequestとResponseとValveContextを引数に取り、invoke内部でValveContext.invokeNextが呼ばれ、その中で次のValve.invokeが呼ばれます。??Valveが次のValveを呼べばいいじゃないか!このくだりは本を読んでいて一番イライラしました*2。
・・・ところが今日このエントリを書いていて、何気にTomcat6のソースを見ると・・・Tomcat5.5以降ではValveContextが撤廃されていました。ヒャッホウ!