2007 年 3 月 11 日 23 時 56 分

.do URL はどのように処理されるか


このアーカイブは同期化されません。 mixi の日記が更新されても、このアーカイブには反映されません。


http://localhost:8080/struts-test/index.do を開くと、
「ログインページ」が表示されたはずだ。

でもこのページは /WEB-INF/pages/login.jsp の内容だ。
でも、ブラウザの URL は /index.do となっている。

で、ものは試しと、以下の URL にアクセスしてみる。
http://localhost:8080/struts-test/WEB-INF/pages/login.jsp
……多分 404 が返ってくるはずである。

何か不思議な感じがしないだろうか?
これに違和感のない人は Servlet をよく理解している。

実は、この挙動は Struts 特有の問題ではなく、
Servlet 自体の仕様に基づいているのだ。

何故このような処理になるかを理解しないまま、
Struts の深い部分に進んでしまうと、
訳が分からなくなってしまう可能性が高い。
そこで、今日はこの仕組みをおさえておこう。

まず、URL にブラウザからアクセスすると、
以下のような処理が行われる。

1. Servlet コンテナが URL へのアクセスを受け取る。
2. 内部で Request と Response オブジェクトを生成する。
3. 対象となる Web アプリケーションを特定する。
4. 要求パスが、/WEB-INF や /META-INF など、
    外部からのアクセスが禁止されているパスの場合は、
    Response に 404 等のエラーを出力して終了。

5. Web アプリケーションの <servlet-mapping> を元に、
    URL を処理する Servlet に転送する。(ディスパッチ)
6. 転送された Servlet が処理を行う。
   Servlet は Response にデータを書き出して終了するか、
   別のパスへの転送を依頼する。(5 番へ)

6 番は、Servlet 固有の処理となっている。

/WEB-INF/pages/login.jsp へのアクセスが弾かれるのは、
/WEB-INF 配下を直接呼び出すことが禁止されているからだ。

では /index.do へのアクセスが何故 JSP で処理されるのか。

http://localhost:8080/struts-test/index.do の場合は、
以下のような流れとなっている。

1. Servlet コンテナが /struts-test/index.do を受け取る。
2. 内部で Request と Response オブジェクトを生成する。
3. Web アプリケーション /struts-test/ を特定する。
4. 要求パス /index.do はアクセスが認められている。
5. /index.do なので、struts に転送される。

6. <Struts ActionServlet の処理>
    Struts の ActionServlet は要求パスから拡張子を取り、
    「/index」のマッピングを設定ファイルから探す。
    /index は /WEB-INF/pages/login.jsp に転送するように
    設定されているので、コンテナを呼び出して、
    /WEB-INF/pages/login.jsp に転送する。

5'. /WEB-INF/pages/login.jsp なので、
    *.jsp にマッピングされた JSP Servlet に転送される。

6'. <JSP Servlet の処理>
    /WEB-INF/pages/login.jsp を処理し、
    Response にデータを書き出して終了する。

実は、このような流れとなっているのである。
ポイントは、「別のパスへの転送」である。

Servlet は連動が可能な仕組みとなっており、
必要であれば他の Servlet を呼び出したり、
異なるパスに転送したりすることができる。

Servlet コンテナが最初に行う転送と少し違うのは、
/WEB-INF 等へのアクセスも可能であるということだ。
(外部からの要求でない限り、確認されない)

もし /index.do から /login.do に転送し、
/login.do から /WEB-INF/login.jsp に転送すれば、
Struts => Struts => JSP と、3 度処理される事になる。

もし /index.do から /login.do に転送し、
/login.do から /index.do に再度転送すれば、
無限ループを作ってしまうことにもなる。

さて、この転送は Servlet 内部でのみ起こっており、
HTTP の転送(リダイレクト)とは直接関係ない。
HTTP のレベルで見れば、1 回の要求 => 応答だけなのである。

Request と Response の寿命は、HTTP 要求の間であり、
Servlet に対する要求の間ではない。
そのため、上記のように Servlet を転々としたとしても、
その属性の値は保存されている。

なので、Struts で前処理をして Request に属性を設定し、
後で JSP でその値を取り出すことなども可能なのである。

この転送機能は非常に強力なのだが、
すこし困った一面もある。

ブラウザから見ると、URL にアクセスし、
サーバからレスポンスが返ってきただけなので、
サーバでどのような処理が行われようと、
当然ながら、ブラウザの URL は要求した時のものだ。

そのため、ブラウザから見ると URL と画面の表示が、
一致しない原因にもなりえるのである。



Copyright (c) 1994-2007 Project Loafer. All rights reserved.