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で配列とか指定するんだと思う……多分……。