「これはヤバかったな」という遅刻エピソード

やさしいJava活用編で勉強しているのですが、

サーブレットコンテキストの説明が書いてなく、ネットで調べても意味不明です。

サーブレットコンテキストは、
javax.servlet.ServletContextインタフェースを実装するクラスのインスタンスで、そのアプリケーションに一つあるとのことですが、

そのサーブレットコンテキストの意味がわからなくて困っています。
HttpSessionのようなもので、クライアントではなく、そのアプリケーションに対して1つあるということですが...
ServletContextオブジェクトは、具体的に何の情報を持っているのですか?


また以下のソースですが、
なぜ指定されたパスにあるリソースを、ラッパーとして機能するRequestDispatcherオブジェクトを返してから、
forwardで転送するのですか?


ServletContext sc = getServletContext();
sc.getRequestDispatcher("/thanks.html").forward(request, response);

A 回答 (3件)

そうですねぇ。

例えて言えば、contextはナースコールみたいなものだとおもいます(「情報を持っている」というだけでなく、用事も頼めるので)。

現代のアプリは、心臓や肺など、基本的な機能をアプリケーションサーバにやってもらっているので、いわば寝たきりの人みたいなものです。
自分で勝手に立って、いろいろやる力がないので、ナースコールを押してサーバにきてもらって、いろいろ助けてもらわないといけない局面があるのですね。

RequestDispatcherは、リモコンみたいなものです。看護士さんは忙しいので、患者がいちいちチャンネルを変えたいときに、毎回テレビをいじりにいく余裕がありません。

ですから、患者が「6チャンネルに変えたい」といったら、「電池を入れて、テレビのほうに向けて、ハイ」という風にセットして、さっさと自分の仕事に戻ってしまいます。

そういうことをしたいので、RequestDispatcherオブジェクトを返してからforwardをやらせる設計にしたんじゃないかと思います。
    • good
    • 1
この回答へのお礼

お礼が遅くなってしまいまして、申し訳ありません。
とてもよく理解できました。

お礼日時:2009/06/21 19:34

コンテキストは一般的に、「コンテナに対するリファレンスである」と考えると分かりやすいかもしれません。



コンテナとは、tomcatやjettyなどのアプリケーションサーバとほぼ同義語と考えてかまいません。

つまり、アプリが、アプリケーションサーバに何かお願いしたいときに使用される参照というわけです。

具体的には、サーブレットが初期化されるときに、コンテナから「僕に用事を頼みたいときにはこれを使ってね」と渡されているはずです。

RequestDispatcherに関しては、http://www.docjar.com/html/api/org/apache/catali …に実装コードがあります。

まずコンストラクタをみると、
/**
157 * Construct a new instance of this class, configured according to the
158 * specified parameters. If both servletPath and pathInfo are
159 * <code>null</code>, it will be assumed that this RequestDispatcher
160 * was acquired by name, rather than by path.
161 *
162 * @param wrapper The Wrapper associated with the resource that will
163 * be forwarded to or included (required)
164 * @param requestURI The request URI to this resource (if any)
165 * @param servletPath The revised servlet path to this resource (if any)
166 * @param pathInfo The revised extra path information to this resource
167 * (if any)
168 * @param queryString Query string parameters included with this request
169 * (if any)
170 * @param name Servlet name (if a named dispatcher was created)
171 * else <code>null</code>
172 */
173 public ApplicationDispatcher
174 (Wrapper wrapper, String requestURI, String servletPath,
175 String pathInfo, String queryString, String name) {
176

いろいろコンテナから情報をもらう必要があるようです。これが、直接インスタンスをユーザに作らせるのではなく、コンテキストのgetRequestDispatcher()メソッドを使う所以と考えられます。
つまり、どうしてもユーザにしか分からない情報("/thanks.html")だけは引数でもらい、あとはコンテナが必要な情報を使ってこのコンストラクタを実行し、RequestDispatcher型のオブジェクトを返してくれる、という設計です。


そこのforwardメソッドを見ると、かなり複雑なことをやっていますね("public void forward"で検索)
セキュリティをチェックしたり、エラーチェックしたり、ログを書いたり、、、

このような処理を、コンテキストの実装クラスにに直接書くことももちろん不可能ではありません。しかし、他にもたくさんある処理を、全部コンテキストの実装クラスに書いたら、そのうちの1つの処理についてコードを変えただけで、クラス全部の処理について、バグが導入されなかったか調べなければいけません。

RequestDispatcherとして分離しておけば、このクラスだけを改変してテストできるので(まぁ、システムテストも結局必要にはなりますが、リスクはかなり小さくなる)、変更や改善がしやすくなります。


オブジェクト指向の基本を抑えた設計ですね。

この回答への補足

tomcatのリファレンスみたいなものですか。
サーバの情報を参照するのですか?

具体的には、サーブレットが初期化されるときに、コンテナから「僕に用事を頼みたいときにはServletContextを使ってね」ということですか?

APIを良く見たら RequestDispatcher オブジェクトを作ることでしか、forwardメソッドを使えませんね。

補足日時:2009/06/14 23:52
    • good
    • 0

> そのサーブレットコンテキストの意味がわからなくて困っています。



サーブレットコンテキストというのは「1つのまとまったWebアプリケーション」のことを言います。

Tomcatを例にして具体的に言うと、通常新規にWebアプリケーションを作成する場合 [TOMCAT_HOME]/webapps ディレクトリ配下に新たにディレクトリ(sample)を作成してその配下にHTML・JSPファイルを、[TOMCAT_HOME]/webapps/sample/WEB-INF/classes ディレクトリ配下にServletで使用する各クラスファイルを置き、[TOMCAT_HOME]/webapps/sample/WEB-INF/web.xml ファイルに設定を記述します。
これで初めてWebアプリケーションが実行できます。

このときの "sample" というのが1つのコンテキストになります。
もしも [TOMCAT_HOME]/webapps ディレクトリ配下に別のディレクトリ(sample02)を作成してWebアプリケーションが実行できる環境を整えれば、これは別のコンテキストになります。


> ServletContextオブジェクトは、具体的に何の情報を持っているのですか?

ServletContextインタフェースは、実体はTomcatなどのServletエンジン側で実装されています。Webアプリケーションの開発者側はServletContextインタフェースに書かれたメソッドを通して各情報を取得します。

参考URLにServletContextインタフェースのAPIリファレンスを載せておきます。

なお通常はこの "sample"や"sample02" という名前を「コンテキスト名」と言います。


> なぜ指定されたパスにあるリソースを、ラッパーとして機能するRequestDispatcherオブジェクトを返してから、
forwardで転送するのですか?

こちらの質問は「HTMLというリソースに対して、なぜわざわざforward()メソッドで転送するのか?」ということでしょうか?

参考URL:http://mergedoc.sourceforge.jp/tomcat-servletapi …

この回答への補足

つまり、その1つのWEBアプリケーションにある、URL、ファイル、パスや、その他様々な情報がつまっているのですね。
APIの方を見たのですが、解説がさっぱりわかりませんでした。
やはり一つ一つ理解するには経験が必要ですね。

どうしてもわからないところとして、
RequestDispatcher オブジェクトです。これを作る理由は
つまり一言で言うとパスを取得するためなのでしょうか?

ラッパーで動作する? の意味がわかりません。

ラッパー: あるプログラムの返り値を別のプログラムに渡すためのプログラムのこと。
つまり、これを作らないと、forwardで転送できないってことだけのことなのでしょうか?(インタフェースRequestDispatcherにforwardメソッドがあるわけですが)


// それぞれ意味を調べてみました。


ServletContext sc = getServletContext();
// これはServletContext()への参照を渡しているだけですね。

sc.getRequestDispatcher("/thanks.html")
/* 指定されたパスに位置するリソースのラッパーとして動作する RequestDispatcher オブジェクトを返します。

クライアントからリクエストを受け取り、さらにそのリクエストをサーバ上の(Servletや HTML ファイル、JSP ファイルのような)リソースに転送するオブジェクトを定義します。
このオブジェクトは特定のパスか、指定された名前で参照できるサーバ上のリソースのラッパーとして使われます。

.forward(request, response);
// RequestDispatcherオブジェクトを使用して、Servletからサーバ上の他のリソース(Servlet, JSP, HTMLファイル)へとリクエストをフォワード(転送)する。

補足日時:2009/06/14 23:25
    • good
    • 0
この回答へのお礼

APIを良く見たら RequestDispatcher オブジェクトを作ることでしか、forwardメソッドを使えませんね。

お礼日時:2009/06/15 00:03

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!

このQ&Aを見た人はこんなQ&Aも見ています


おすすめ情報

このQ&Aを見た人がよく見るQ&A