結論としては、@higayasuo さんがお話されていた通り「当たり前の挙動」を示しているだけなのかなーと。
サーブレットに詳しくない自分としてはちょっとツラい感じです
※6/9修正しました。ソース部分をasXxxを使った形に書き換え&こちらを参考にrequestなどの取得について修正
確認しました。
POSTが噛んだときの、マッピングの判断条件の考え方が間違っていました。
RequestMapのgetは、内部でHttpRequestServletのgetAttribute()を呼び出します。
で。
- Formのenctypeが「multipart/form-data」の場合
POSTがない場合はこれでGETの引数としてのマッピング先(?key={key})が取得できるのですが、POSTデータがある場合はこの値がPOSTの内容になるようです。
GETの値はどこかというと、「request.getParameter("key")」で取得できる模様
 - Formのenctypeが「text/plain」の場合
RequestMapのgetは、GETの値、つまりURLマッピングの「?key={key}」が入っています。
POSTの値は・・・getParameterでも取れませんでした。 
とりあえずURLマッピングを絡めてPOSTを扱う場合は、「multipart/form-data」にしておくことをオススメします。
以下修正しました。
ひと通り動く版。POSTは「multipart/form-data」で。
参照リンク
http://sites.google.com/site/slim3documentja/documents/slim3-controller/url-mapping
Slim3は通常、
というようにマッピングルールに基づいて、実行するコントローラが決まります。※slim3.rootpackage は web.xml で定義されています。
リクエストURLパス コントローラ / slim3.rootpackage.controller.IndexController /xxx slim3.rootpackage.controller.XxxController /xxx/ slim3.rootpackage.controller.xxx.IndexController /xxx/yyy slim3.rootpackage.controller.xxx.YyyController /xxx/yyy/zzz slim3.rootpackage.controller.xxx.yyy.ZzzController 
リンク先に書いてあるのをちゃんと読んでいなかったのですが、このURLマッピングはある程度制御することができます
コントローラを取得する前にリクエストURLパスの書き換えをすることもできます。
URLリライティングを使うには slim3.rootpackage.controller.AppRouter クラスを先に定義する必要があります。
とのこと。実際にやってみましょう
slim3.rootpackageが「jp.tyato.test」だとすると、「jp.tyato.test.controller.AppRouter」クラスを生成します
- 「jp.tyato.test.controller」のパッケージを用意する
 - 「jp.tyato.test.controller」配下に「AppRouter」クラスを生成。内容は次のような感じ
 
6/8修正
package jp.tyato.test.controller;
import org.slim3.controller.router.RouterImpl;
public class AppRouter extends RouterImpl
{
    Public AppRouter()
    {
        addRouting("/xxx/{key}", "/xxx?key={key}");
    }
}
次にIndexControllerクラスを生成します
- 「build.xml」を開き、アウトラインから「gen-controller-without-view」を選択、実行から「1 Ant ビルド」を実行する
 - 名前の入力を求められるので、「/xxx/Index」と入力
 - 「jp.tyato.test.controller.xxx」配下に「IndexController.java」が作成される
 - メソッド「run」の中を書き換える
 
final String KEY_NAME = "key";
@Override
public Navigation run() throws Exception
{
    Navigation result = null;
    try
    {
        String keyword = asString(KEY_NAME);
        if(keyword == null)
        {
            //getParameterで再度試行
            keyword = request.getParameter(KEY_NAME);
        }
        if( keyword != null )
        {
            keyword = keyword.toLowerCase();
        }
        //Factoryパターン用コントローラ親クラスの定義
        Controller con = this.GetFromFactory(keyword);
        result = con.runBare();
    }
    catch (Throwable e)
    {
        e.printStackTrace();
    }
    return result;
}
public Controller GetFromFactory(String keyword)
{
    Controller con = null;
    try
    {
        if (keyword == null || keyword.isEmpty() || keyword.startsWith("index") )
        {
            //keywordがnull、空文字、indexで始まる文字のいずれかである場合、Index表示処理
            con = new ForDefaultController();
        }
        else if (keyword.equals("yyy"))
        {
            //keyが「yyy」である場合、yyy用の処理へ
            con = new YyyController();
        }
        else if (keyword.equals("zzz"))
        {
            //keyが「zzz」である場合、zzz用の処理へ
            con = new ZzzController();
        }
    }
    catch (Exception e)
    {
        e.printStackTrace();
    }
    return con;
}
後は実際に処理を行うControllerクラスを実装します。この場合は「ForDefaultController」「YyyController」「ZzzController」について
- 「build.xml」を開き、アウトラインから「gen-controller-without-view」を選択、実行から「1 Ant ビルド」を実行する
 - 名前の入力を求められるので、「/xxx/???」と入力
 - 「jp.tyato.test.controller.xxx」配下に「???Controller.java」が作成される
 
しかしこのままですと、各Controllerを呼び出してもそれぞれの変数である
「protected ServletContext servletContext」
「protected HttpServletRequest request」
「protected HttpServletResponse response」
がnullのままです。
ですので、利用する前に各Locaterのgetを使って、値を取得してやります。
YyyControllerであれば、こんな感じです
package jp.tyato.test.controller.xxx;
import org.slim3.controller.Controller;
import org.slim3.controller.Navigation;
import org.slim3.util.RequestLocator;
import org.slim3.util.ResponseLocator;
import org.slim3.util.ServletContextLocator;
public class YyyController extends Controller
{
    @Override
    public Navigation run() throws Exception
    {
        this.CheckParentMember();
        //以降、実処理
    }
    protected void CheckParentMember()
    {
        if( request == null )
        {
            request = RequestLocator.get();
        }
        if( response == null )
        {
            response = ResponseLocator.get();
        }
        if( servletContext == null )
        {
            servletContext = ServletContextLocator.get();
        }
    }
}
「ForDefaultController」「ZzzController」についても同様に定義してやります。※まぁ実際に使うときに〜Locator.get()を呼び出してやればいいんですが。
こうすることで、
- Indexに一旦集約
 - その都度の値により狙った処理を行うように制御
 
0 件のコメント:
コメントを投稿