このアーカイブは同期化されません。 mixi の日記が更新されても、このアーカイブには反映されません。
昨日は、ActionForward クラスを使って転送を行ったが、
ActionForward インスタンスをその場で作成しているため、
アクションのコード中に URL がハードコーディングされる。
確かに Model と View のコードは切り離されたが、
両者の依存性(結合性)は未だに高く、
この Model を実行するとこの View に移動するという、
遷移が固定されていることには変わりない。
「Model の部品化」という点で考えてみると、
Model は動作だけに専念すべきである。
処理を行って処理結果を格納し、成否を返すだけで良く、
Model が自身の遷移先を決める必要はないはずだ。
そこで、今日は Model から状態遷移を切り離してみよう。
LoginAction を例として考えてみると、
このアクションは「ログイン処理」という動作なのだから、
認証が必要な色々な場所で使えるはずだが、
昨日のコードでは、必ずメニュー画面に飛んでしまう。
これを防ぐためにはどうすればよいか。
実は、設定ファイルの <action> 要素には、自分の子として、
<forward> 要素を記述することができる。
<forward> 要素は、ActionForward を XML 化したもので、
これを使うと、事前に転送先を用意しておくことができる。
<action path="/login"
type="jp.loafer.test.actions.LoginAction">
<forward name="success" path="/WEB-INF/pages/menu.jsp" />
<forward name="failure" path="/WEB-INF/pages/login.jsp" />
</action>
<forward> 要素の path 属性には転送先のパスを、
name 属性には自由な名前をつけることができる。
上記の例では、success(成功)は menu.jsp への、
failure(失敗)は login.jsp への転送を意味している。
では、この情報をどのように使うか。
例によって、Action の execute メソッドを見てみよう。
public ActionForward execute(
ActionMapping mapping,
ActionForm form,
HttpServletRequest request,
HttpServletResponse response) throws Exception;
今回使うのは、ActionMapping クラスである。
ActionMapping クラスは、struts-config.xml に記述した、
<action> 要素の設定内容を Bean 化したものだ。
そのため、アクションクラスの execute メソッドでは、
mapping 引数を使って設定内容を読み取る事ができる。
ActionMapping の FindForward メソッドを使うと、
<action> 要素の子として定義した <forward> 要素を、
その name 属性を元にして検索することができる。
戻り値は、ActionForward インスタンスとして返るため、
そのまま execute メソッドの戻り値とすることができる。
では、これを利用して、昨日のコードを改造してみよう。
========== LoginAction#execute ==========
public ActionForward execute(ActionMapping mapping,
ActionForm form, HttpServletRequest request,
HttpServletResponse response) throws Exception {
// パラメータを取得
String user = request.getParameter("user");
String password = request.getParameter("password");
// ユーザ名は guest 限定とする
if (!"guest".equals(user)) {
return mapping.findForward(Forwards.FAILURE_KEY);
}
// パスワードは hogehoge 限定とする
if (!"hogehoge".equals(password)) {
return mapping.findForward(Forwards.FAILURE_KEY);
}
// ログイン成功!
// ログイン情報をセッションに保存
request.getSession().setAttribute("user",
request.getParameter("user"));
return mapping.findForward(Forwards.SUCCESS_KEY);
}
========== end of LoginAction#execute ==========
今日は少しだけロジックも仕込んでみた。
入力パラメータを調べ、ユーザ名とパスワードが、
「guest」かつ「hogehoge」の場合のみログイン成功、
それ以外なら失敗とみなす。
アクションは、ActionMapping を使って成否を返す。
成功時には "success"、失敗時には "failure" というキーで
ActionMapping を検索してそれを返すのだ。
ソースコード上に、"failure" 等の文字列リテラルを、
大量に書かないようにするため、
<forward> の名前は定数化しておいた。
========== Forwards.java ==========
package jp.loafer.test.actions;
public class Forwards {
static public final String FAILURE_KEY = "failure";
static public final String SUCCESS_KEY = "success";
private Forwards() {}
}
========== end of Forwards.java ==========
では、/index.do をブラウザで開き、
ログインフォームに入力して送信してみよう。
guest/hogehoge の組み合わせの場合のみ、
「ログイン成功!」の画面に転送され、
それ以外の場合は、ログイン画面に戻されるはずだ。
これでアクションから URL を消すことができた。