getRequestDispatcher foward
Strutsをはじめ、上記のようにリクエストのフォワーディングをおこなうことは少なくないのではないでしょうか?URLReWriteのような形で特定のURLパターンにマッチした場合にアドレスを変換したり、*.html のアドレスでアクセスされた場合に内部的には、*.jsp や、*.do などの動的な処理に転送したい場合などが考えられる。
また、サイトにアクセス制御がかけられている場合は、認証されていない場合にログイン画面に転送するなどにも利用される。
Struts2での問題
ここで今まで利用してきた Struts1では、上記のような処理を、通常、web.xml で設定された、フィルターの機能を利用しておこなっていた方も多いのでしょうか?これは非常に簡単なコーディングにてリクエストの転送を問題なくおこなえていました。
web.xml
<filter>
<filter-name>accessFilter</filter-name>
<filter-class>com.pg2se.AccessFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>accessFilter</filter-name>
<url-pattern>/security/*</url-pattern>
</filter-mapping>
<servlet>
<servlet-name>action</servlet-name>
<servlet-class>org.apache.struts.action.ActionServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>action</servlet-name>
<url-pattern>*.do</url-pattern>
</servlet-mapping>
com.pg2se.accessFilter#doFilter
if (checkLogin == false) {
request.getRequestDispatcher(“/login.do”).forward(req, res);
} else {
chain.doFilter(req, res);
}
同様の処理を Struts2 に移植または実装しようとした際に、何も考えずコーディングした場合に、リクエストのフォワードがうまく動作しない現象が発生してしまうのではないでしょうか?
具体的には、
request.getRequestDispatcher(“/login.action”).forward(req, res);
と記述しても、
“/logon.action” is not available
となってしまいます。最初は原因はわからなくて戸惑うかも知れませんが、これは、Struts1 と Struts2 のアクションが起動される仕組みが変更されているからです。
web.xml
<filter>
<filter-name>AccessFilter</filter-name>
<filter-class>com.pg2se..AccessFilter</filter-class>
</filter>
<filter>
<filter-name>struts2</filter-name>
<filter-class>org.apache.struts2.dispatcher.FilterDispatcher</filter-class>
</filter>
<filter-mapping>
<filter-name>AccessFilter</filter-name>
<url-pattern>/security/*</url-pattern>
</filter-mapping>
<filter-mapping>
<filter-name>struts2</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
Struts2 では、一般的に、上記のように記述しているのではないでしょうか?
この、Struts1 の記述と、Struts2 での記述の違いをみると、アクションの起動が、Struts1 では、servlet-mapping が利用されているのに対し、Struts2 は、filter-mappping を利用しているという点です。
AccessFilter の中で、Struts1と同じように、getRequestDispatcherで、foward をおこなっても、アクションは起動されないようになっている。なぜなら、Struts2 では、アクションはフィルターで動作するようになっおり、デフォルトでは、リクエスト時にはフィルターが呼び出されるが、foward時にはフィルターが呼び出されないようになっているからである。
これを回避するのは意外と簡単で、web.xml で設定できる。
設定の詳細はこちらのページで詳しく書かれています。
web.xml
<filter-mapping>
<filter-name>struts2</filter-name>
<url-pattern>/*</url-pattern>
<dispatcher>FORWARD</dispatcher>
<dispatcher>REQUEST</dispatcher>
</filter-mapping>
アクションの、filter-mapping にて、<dispatcher>要素を記述する。
記述できる値は、REQUEST、FORWARD、INCLUDE、ERROR である。
ここで、FORWARDを指定すれば、getRequestDispatcher#foward をおこなった際にも、
該当のフィルターが起動され目的の処理をおこなうことができるようになる。