第8章 要求のディスパッチ (Dispatching
Requests)
ウェブ アプリケーションを構築するとき、要求の処理を別のサーブレットに転送する、あるいは別のサーブレットの出力を応答に含めることができると有用である。RequestDispatcherインターフェイスはこれを実現するメカニズムを与えるものである。
8.1 RequestDispatcherの取得 (Obtaining a RequestDispatcher)
RequestDispatcherインターフェイスを実装したオブジェクトは、ServletContextから次のメソッドを介して取得できる:
- getRequestDispatcher
- getNamedDispatcher
getDispatcherメソッドは、ServletContextのスコープ内のパスを記述するStringの変数をとる。このパスはServletContextのルートに対して相対でなければならない。このパスはサーブレットをルックアップし、それをRequestDispatcherオブジェクトにラップし、それを返す。与えられたパスではサーブレットはひとつも得られないときは、返されるRequestDispatcherは単にそのパスのコンテンツのみで返される。
getNamedDispatcherは、ServletContextで知られたサーブレット名を示すString型の変数を取る。あるサーブレットが与えられた名前でServletContextに知られているときは、それはRequestDispatcherオブジェクトでラップされ、返される。その与えられた名前では関連付けられるサーブレットが存在しないときは、このメソッドはヌル(null)を返さなければならない。
RequestDispatcherオブジェクトが、ServletContextのルートに相対ではではないが、その代り現在の要求のパスに相対であるような相対パスを使って取得できるようにするには、ServletRequestインターフェイスには次のようなメソッドが用意されている:
- getRequestDispatcher
このメソッドの振舞いはServletContextにある同じ名前の同じであるが、動作のための変数の部分として与えられるために、コンテキスト内に完全なパスを要求しない。サーブレットコンテナはその要求オブジェクト内の情報を与えられた相対パスから完全なパスに変換するのに使用できる。例えば、’/’にあるコンテキストルート、/garden/tools.htmlへの要求、ServletRequest.getRequestDispatcher(“header.html”)を介して得られた要求ディスパッチャは、ServletContext.getRequestDispatcher(“/garden/header.html”)を呼んだと全く同じ振舞いを示す。
8.1.1 要求ディスパッチャ パスのクエリ ストリング (Query
Strings in Request Dispatcher Path)
パス情報を使ってRequestDispatcherを生成できるServletContextとServlerRequestでは、そのパスにオプショナルとしてクエリの文字ストリング情報を付けることが出来る。例えば、開発者は以下のコードを使ってRequestDispatcherを取得してもよい:
String path = “/raisons.jsp?orderno=5”;
RequestDispatcher rd = context.getRequestDispatcher(path);
rd.include(request, response);
クエリ文字列の内容はパラメタのセットに追加され、それに含まれるサーブレットがアクセスできる。パラメタは順番付けられており、RequestDispatcherを生成するのに使われたクエリ文字列で指定されたどのパラメタも優先性を持つ。RequestDispatcherに関連付けされたパラメタは、includeまたはforward呼び出しの期間にのみのスコープとなる。
8.2 要求ディスパッチャの使用 (Using a Request Dispatcher)
要求ディスパッチャを使用するには、開発者はRequestDispatcherインターフェイスのincludeまたはforwardメソッドのいずれかを、Servletインターフェイスのserviceメソッドを介して渡されたrequestとresponseの変数を使って呼び出す必要がある。
コンテナのプロバイダは、必ず元の要求と同じ同一VMのスレッド内に、ターゲットのサーブレットへの配送が生ずるようにしなければならない。
8.3 インクルード (Include)
RequestDispatcherインターフェイスのincludeメソッドは何時でも呼ばれてもよい。ターゲットのサーブレットはその要求オブジェクトの全てのアスペクトにアクセスできるが、応答バッファの終わり以上にコンテンツを書き込むかあるいは明示的にServletResponseインターフェイスのflushメソッドを呼ぶかで応答をコミットする権限とともに、応答オブジェクトのServletOutputStreamまたはWriterにのみに情報を書き込むことが出来る。インクルードされたサーブレットはヘッダをセットできないし、応答のヘッダに影響を及ぼすどのメソッドも呼ぶことは出来ない。
8.3.1 インクルードされた要求パラメタ (Included Request Parameters)
あるサーブレットがあるinclude内で使用されているときは、時にはそのサーブレットが、それが呼ばれかつ元の要求パスではないパスを知る必要がある。以下の要求の属性がセットされる:
javax.servlet.include.request_uri
javax.servlet.include.context_path
javax.servlet.include.servlet_path
javax.servlet.include.path_info
javax.servlet.include.query_string
これらの属性はインクルードされたサーブレットからはrequestオブジェクトのgetAttributeメソッドを介してアクセスできる。
インクルードされたサーブレットは、NamedDispatcherを使って取得されたが、これらの属性はセットされない。
8.4 転送 (Forward)
RequestDispatcherインターフェイスのforwardメソッドは、そのクライアントへの出力がコミットされていないときに呼び出しサーブレットから呼ばれる。応答のバッファにコミットされていない出力が存在するときは、ターゲットのサーブレットのserviceメソッドが呼ばれる前にリセット(バッファのクリア)されていなければならない。応答がコミットされてしまっているときは、IllegalStateExceotion例外がスローされねばならない。
ターゲットのサーブレットに開示された要求オブジェクトのパス要素は、RequestDispatcherを取得するときに使ったパスを反映していなければならない。これの唯一の例外は、RequestDispatcherがgetNamedDispatcherメソッドを介して取得されたときである。この場合、要求オブジェクトのパス要素は元の要求のそれを反映する。
RequestDispatcherインターフェイスのforwardメソッドが戻る前に、その応答はサーブレット コンテナによりコミットされ、閉じられねばならない。
8.5 誤り処理 (Error Handling)
要求ディスパッチャのターゲットからスローされたとき、ランタイム例外と、ServletExceptionまたはIOException型のチェック済み例外だけが呼び出しサーブレットに伝播されねばならない。その他の全ての例外は、ServletExceptionでラップされ、その例外の根因は元の例外にセットされる。