Slim3でのURLマッピング


再度確認しました
 結論としては、@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は通常、

リクエスト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

※slim3.rootpackage は web.xml で定義されています。

というようにマッピングルールに基づいて、実行するコントローラが決まります。

リンク先に書いてあるのをちゃんと読んでいなかったのですが、この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」が作成される

???の部分をそれぞれ「ForDefault」「Yyy」「Zzz」に置き換えて読んでください。

しかしこのままですと、各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に一旦集約
  • その都度の値により狙った処理を行うように制御

といったことが可能になります。


7年 ago

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です