アクションとは特定の URI へのリクエストに対応する処理で、Cubby のユーザーが実装する部分です。
URI に対応するメソッドをアクションメソッド、アクションメソッドが定義されたクラスをアクションクラスといいます。
アクションクラスに定義されたメソッドのうち、アクセス修飾子が public で戻り値が ActionResult
のメソッドをアクションメソッドとして認識します。
このメソッドは AOP によってエンハンスされ、メソッド実行時に以下の処理が実行されるようになります。
これらは AOP によってメソッド自体がエンハンスされるため、アクションメソッドの中から他のアクションメソッドを呼び出した場合も上記の処理が実行されます。
以下のクラスは ActionResult を実装するクラスで、アクションメソッドの戻り値として使用できます。
| クラス名 | 説明 |
| Forward | 指定されたパスにフォワードします。 |
| Redirect | 指定されたパスにリダイレクトします。 |
| Direct | 何も処理を行いません。アクションメソッド中でレスポンスに直接書き込みます。ファイルや画像をブラウザに返す時に使用します。 |
| Json | 指定されたオブジェクトを Json 形式に変換してレスポンスを返します。 |
アクションクラスやアクションメソッドに以下のアノテーションを指定することで、アクションのメタ情報を設定することができます。
| アノテーション名 | 説明 | 省略した場合 |
| @Path | アクションメソッドに対応する URI を指定します。 | XxxAction#yyyy() の場合は /xxx/yyyy になります。 |
| @Accept | アクションメソッドが受け付ける HTTP メソッドを指定します。 | GET と POST に対応するメソッドになります。 |
| @Form | リクエストパラメータをバインドするオブジェクトを指定します。 | アクションクラスのインスタンスになります。 |
| @Validation | 入力検証を定義したプロパティを指定します。 | 入力検証を行いません。 |
アクションクラスにある以下のメソッドをオーバーライドすることで、アクションメソッド実行の前後にフック処理を記述することができます。
また、アクションメソッド実行の前後に処理を組み込みたい場合は、Seasar の AOP
を使用して処理をフックします。
| メソッド名 | 説明 |
| Action#initialize | アクションメソッドの実行前に呼ばれます。パラメータのバインディング前に呼ばれるので、パラメータを使用したい場合はリクエストから直接取得する必要があります。 |
| Action#prerender | フォーワードの直前で呼ばれます。対象のActionクラスのフォワード先で必ず使用する共通のデータなどを取得する目的で使用します。 |
| Action#postrender | フォワードの直後で呼ばれます。通常はあまり使用することはないでしょう。 |
アクションの単体テストは CubbyTestCase を使用します。 Seasar の S2Unit の機能を全て使用できるので SeasarのS2Unitのドキュメント も合わせてご覧ください。
HelloActionTest.java
package org.seasar.cubby.examples.other.web.hello;
import org.seasar.cubby.action.ActionResult;
import org.seasar.cubby.action.Forward;
import org.seasar.cubby.unit.CubbyTestCase;
public class HelloActionTest extends CubbyTestCase {
// 対象のアクション
private HelloAction action;
// 初期化処理
protected void setUp() throws Exception {
// diconファイルの読み込み
include("app.dicon");
}
public void testIndex() throws Exception {
// アクションの実行
ActionResult result = processAction("/hello/");
// 結果のチェック
assertPathEquals(Forward.class, "input.jsp", result);
}
public void testMessage() throws Exception {
// リクエストパラメータのセット
getRequest().addParameter("name", "name1");
// アクションの実行
ActionResult result = processAction("/hello/message");
// 結果のチェック
assertPathEquals(Forward.class, "result.jsp", result);
// 実行後のアクションの状態を確認
assertEquals("name1", action.name);
}
}
TodoActionTest.java
package org.seasar.cubby.examples.todo.action;
import org.seasar.cubby.action.ActionResult;
import org.seasar.cubby.action.Forward;
import org.seasar.cubby.action.Redirect;
import org.seasar.cubby.examples.RunDdlServletRequestListener;
import org.seasar.cubby.unit.CubbyTestCase;
public class TodoActionTest extends CubbyTestCase {
private TodoAction action;
protected void setUp() throws Exception {
include("app.dicon");
RunDdlServletRequestListener listener = new RunDdlServletRequestListener();
listener.requestInitialized(null);
}
@Override
protected void setUpAfterBindFields() throws Throwable {
super.setUpAfterBindFields();
getRequest().addParameter("userId", "test");
getRequest().addParameter("password", "test");
// 後続のテストを実行するためにログインアクションを実行
assertPathEquals(Redirect.class, "/todo/", processAction("/todo/login/process"));
}
public void testShow() throws Exception {
this.readXlsAllReplaceDb("TodoActionTest_PREPARE.xls");
// CoolURIの場合のテスト
ActionResult result = processAction("/todo/1");
assertPathEquals(Forward.class, "show.jsp", result);
assertEquals(new Integer(1), action.id);
assertEquals("todo1", action.text);
assertEquals("todo1 memo", action.memo);
assertEquals(new Integer(1), action.todoType.getId());
assertEquals("type1", action.todoType.getName());
assertEquals("2008-01-01", action.limitDate);
}
}