mod_rewriteを使用したパラメーター付加。
これまた面倒な、mod_rewriteを使用したパラメーター付加。
以前めんどくさいことが判明したわけですが、mod_rewriteと組み合わせるとさらにめんどくさくなります(爆)。上記で説明しましたが、普通のHTML形式のURLにリダイレクトをする場合、JSP側で<logic:redirect>タグを使用する必要があり、しかもそこにパラメーターをくっつけなきゃいけないからです。
画面遷移は、次のようにしました。見方は「アドレス欄のURL(呼び出すサーブレット/フォワードするJSP)」です。また、URLもサーブレットもhttp://localhost/がついているものとみなしてください。
/Search/index.html(/webapp-search/Start.do/start.jsp) ↓ ?????(/webapp-search/Search.do/search_redirect.jsp) ↓ /Search/search?query=AAA(/webapp-search/Search.do/search_result.jsp)
途中の「?????」は、リダイレクト中なのでURL表記が出ないためこう表現しました。
さて、さまざまな問題が待ちかまえています!
・URLが変えられた状態でPOSTしたら?
/Search/index.htmlからPOSTする場合、その指定方法はどうすればいいのでしょうか。
start.jspに以下のように記述した場合、
<html:form action="Search" >
/Search/Search.doされちゃいそうです。
が、実はされません。ちゃんと/webapp-search/Search.doが呼ばれます。
なのでこれは問題なし。
・mod_rewriteとリダイレクト。
前述の通り、StrutsでURLにパラメーターを付加する、つまりsearch?query=AAAみたいなURLにしたい場合、リダイレクトを使用する必要があります。
前回はRedirectingActionForwardを使用しましたが、Struts1.2以降の場合、この方法では/webapp-search/の外へのリダイレクトができません。mod_rewriteを使用する場合、これだと困ります。そこで、JSP側でリダイレクトします。search_redirect.jspを以下のようにします。
<%@ page contentType="text/html; charset=Shift_JIS" pageEncoding="Shift_JIS" %> <%@ taglib uri="/WEB-INF/lib/struts-html.tld" prefix="html" %> <%@ taglib uri="/WEB-INF/lib/struts-logic.tld" prefix="logic" %> <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> <html:html> <logic:redirect href="/Search/search" paramId="query" paramName="query"/> </html:html>
さらに、httpd.confでのRewriteRule指定を以下のようにします。
RewriteRule ^/Search/search?(.+)$ /webapps-search/Search.do?is_redirect=true$1 [P,L]
こうすることで、search_redirect.jspに遷移後、パラメーターが付いたURL形式でリダイレクトされ、さらにそれが変換されてサーブレットへと渡されるわけです。
・パラメーターを付加する。
<logic:redirect>を使用してリダイレクトする場合、ラッキーなことにパラメーターを?でくっつける必要がありません。
<logic:redirect href="/Search/search" paramId="パラメーターの名前" paramName="セットする値が入ってる属性の名前"/>
のように指定することで
/Search/search?パラメーターの名前=「属性の名前」が持つ値
とゆーURLを作ってリダイレクトしてくれます。*1
属性に値をセットするのは以下のようにします。
// SearchAction.javaのSearchAction#execute()内。 // パラメーターを取り出します。 DynaValidatorForm dynaForm = (DynaValidatorForm)form; // index.htmlの検索項目がqueryという名前の場合。 String query = (String)dynaForm.get( "query" ); // その検索項目を属性にセットします。 // 第1引数が「セットする値が入ってる属性の名前」です。 // 第2引数が「「属性の名前」が持つ値」です。 request.setAttribute( "query", query ); // search_redirect.jsp へ遷移。 return mapping.findForward( "search_redirect" );
ちなみにstruts-config.xmlは以下のようにしてます。
<!-- 検索フォーム。 --> <form-bean name="SearchForm" dynamic="true" type="org.apache.struts.validator.DynaValidatorForm"> <form-property name="query" type="java.lang.String" /> <form-property name="is_redirect" type="java.lang.String" /> </form-bean> <!-- ... --> <!-- 検索実行。 --> <action path="/Search" type="action.SearchAction" name="SearchForm" scope="request" validate="true"> <forward name="search_redirect" path="/WEB-INF/jsp/search_redirect.jsp"/> <forward name="search_result" path="/WEB-INF/jsp/search_result.jsp"/> </action>
複雑だ……。
・ループさせない。
今回の方法では、Search.doから再びSearch.doにリダイレクトしています。
そのため、ストップさせるようにしないと永久ループしてしまいます。
今回は、RewriteRuleでフラグを付加させました。
RewriteRule ^/Search/search?(.+)$ /webapps-search/Search.do?is_redirect=true$1 [P,L]
この中のis_redirect=trueがそうです。
このフラグをSearchAction#execute()の中でチェックします。
// SearchAction.javaのSearchAction#execute()内。 // パラメーターを取り出します。 DynaValidatorForm dynaForm = (DynaValidatorForm)form; String is_redirect = (String)dynaForm.get( "is_redirect" ); if ( ( is_redirect != null ) && ( is_redirect.equals( "true" ) ) ) { return mapping.findForward( "search_result" ); }
このようにして2周目、もしくはURL直打ちされた場合にはリダイレクトせず検索結果へとフォワードする用にすればOK。
……めんどくさ……。
まぁ、この辺の画面まわりが実現できるか不安だったんだけど、なんとかなりそうだな……。
>追記。
間違ってました。
*1:じゃあパラメーターの数が複数ならどうするんだ? というと……多分nameで配列とか指定するんだと思う……多分……。