How are path related values of the request object changed after a forward or include?
winstoneのRequestDispatcherを覗いているときに発見した事実。つーか,正直あまり気にしたこと無かった。
RequestDispatcher.include()/forward()したときのRequest URIの挙動について。includeの方は,Servlet2.3のころ(SRV.8.3.1)から定義されていたようなのだが,forwardは,Servlet2.4(SRV.8.4.2)で定義されたもよう。
#まあ,どっちも知らなかったんで,威張って言うほどのモノではない。:-)
ここにも書いてあった。
→Servlet 2.4: What's in store - RequestDispatcher changes
ここからテストした結果を記すよ。
まずはテストページのコード。
== test1.jsp == <pre> request uri: ${pageContext.request.requestURI} context path: ${pageContext.request.contextPath} servlet path: ${pageContext.request.servletPath} path info: ${pageContext.request.pathInfo} query string: ${pageContext.request.queryString} foo : ${param["foo"]} </pre> <jsp:include page="include.jsp?foo=override" /> FOO : ${param["foo"]} == include.jsp == <hr> Include: <pre> request uri: ${pageContext.request.requestURI} context path: ${pageContext.request.contextPath} servlet path: ${pageContext.request.servletPath} path info: ${pageContext.request.pathInfo} query string: ${pageContext.request.queryString} foo : ${param["foo"]} ----------- javax.servlet.include.request_uri: ${requestScope["javax.servlet.include.request_uri"]} javax.servlet.include.context_path: ${requestScope["javax.servlet.include.context_path"]} javax.servlet.include.servlet_path: ${requestScope["javax.servlet.include.servlet_path"]} javax.servlet.include.path_info: ${requestScope["javax.servlet.include.path_info"]} javax.servlet.include.query_string: ${requestScope["javax.servlet.include.query_string"]} </pre> <hr>
フォワード版はこんなの。
== test2.jsp == <jsp:forward page="forward.jsp?foo=override" /> == forward.jsp == Forward: <pre> request uri: ${pageContext.request.requestURI} context path: ${pageContext.request.contextPath} servlet path: ${pageContext.request.servletPath} path info: ${pageContext.request.pathInfo} query string: ${pageContext.request.queryString} foo : ${param["foo"]} ----------- javax.servlet.forward.request_uri: ${requestScope["javax.servlet.forward.request_uri"]} javax.servlet.forward.context_path: ${requestScope["javax.servlet.forward.context_path"]} javax.servlet.forward.servlet_path: ${requestScope["javax.servlet.forward.servlet_path"]} javax.servlet.forward.path_info: ${requestScope["javax.servlet.forward.path_info"]} javax.servlet.forward.query_string: ${requestScope["javax.servlet.forward.query_string"]} </pre>
まず,インクルードについてテストしてみんとす(以下のURLでアクセス)。
test1.jsp?foo=hogehoge
パラメタ:fooの値(hogehoge)が上書きされるかどうかがポイント。結果はこう。
request uri: /WebApplication3/index.jsp
context path: /WebApplication3
servlet path: /index.jsp
path info:
query string: foo=hogehoge
foo : hogehoge
- -
Include:
request uri: /WebApplication3/index.jsp
context path: /WebApplication3
servlet path: /index.jsp
path info:
query string: foo=hogehoge
foo : override
-----------
javax.servlet.include.request_uri: /WebApplication3/include.jsp
javax.servlet.include.context_path: /WebApplication3
javax.servlet.include.servlet_path: /include.jsp
javax.servlet.include.path_info:
javax.servlet.include.query_string: foo=override
- -
FOO: hogehoge
インクルードされる側のパラメタは上書きされて送られる。んでもって,インクルードされる側のJSP名とかは,リクエストの属性:javax.servlet.include.*で取得できる。
つづいて,フォワードについてテスト。
test2.jsp?foo=hogehoge
インクルードと同じようなURLを投げて,パラメタ:fooの値がどうなるかチェックする。
とりあえず,結果はこう。
Forward:
request uri: /WebApplication3/forward.jsp
context path: /WebApplication3
servlet path: /forward.jsp
path info:
query string: foo=override
foo : override
-----------
javax.servlet.forward.request_uri: /WebApplication3/index_1.jsp
javax.servlet.forward.context_path: /WebApplication3
javax.servlet.forward.servlet_path: /index_1.jsp
javax.servlet.forward.path_info:
javax.servlet.forward.query_string: foo=hogehoge
インクルードと違ってフォワードの場合,フォワード元(test2.jsp)は表示されることはないので,RequestURIとかは,フォワード先(forward.jsp)の値になる。だから,パラメタ:fooも上書きされた値しか取れない(QUERY_STRINGも上書き)。
でも,Servlet2.4からはフォワード元の情報が,リクエストの属性:javax.servlet.forward.*に格納されるようだ。
ついで言うと,ServletContext.getNamedDispatcher(String)の場合は,これらの追加属性(javax.servlet.includeやforward)は付加されないそうな。
「だからどうした?」的な話であるが,知らんかったんでメモ。