Super Agile Struts (SAStruts)

SAStrutsはSeasarプロジェクトのWebフレームワーク。ActionやFormの扱いがStrutsとは大きく違うため、Struts上に作った別のフレームワークと考えると良いかもしれない。

バリデーションや画面遷移をアノテーションで指定出来るため、Struts特有の設定ファイルが要らずコードに集中でき書きやすい。

使ってみる

EclipseとDoltengプラグインを使ってSAStrutsのプロジェクトを作る。パッケージ名だけ最初に決める必要がある。

基本的な使い方

ActionはタダのJava Object (POJO) でStruts Actionクラスを継承する必要は無い。

package jp.paulownia.test.action;
 
public class HogeAction {
    @Required
    public String id;     // パラメータでnameが送られてくるとココに入っている。
 
    @Execute(validation=false)   // このアクションメソッドではバリデーションしない
    public String list() {
        return "list.jsp";
    }
 
    @Execute(input="list")   // このアクションメソッドでは検査する。エラー時はlistメソッドを実行する
    public String edit() {
        return "edit.jsp";
    }
}

というアクションがある場合、  http://example.com:8080/context_path/hoge/edit へアクセスすると

jp.paulownia.test.action.HogeAction#edit

メソッドが呼ばれる。そしてメソッドの戻り値で指定した

/WEB-INF/view/hoge/edit.jsp

のJSPを実行する。(/hoge/はアクション名から自動補完される。)

  • URLとマッピングするメソッドには@Executeアノテーションを付ける
  • ダウンロード等遷移先が無い場合@Executeなメソッドの戻り値をnullにする
  • リダイレクトは /hoge/edit?redirect=trueとか戻すとリダイレクトしてeditメソッドの呼び出し
  • 他のアクションにforwardするときは、/ で始める?

Actionの下にパッケージを作ってそこにActionを置くと、URLのパスが深くなる

http://example.com:8080/context_path/fuga/hige/edit
package jp.paulownia.test.action.fuga;
 
public class HigeAction {
    @Execute(validation=false)
    public String edit() {
        return "edit.jsp";
    }
}

遷移先を指定する戻り値とinputの値はjsp名、またはアクションメソッド名。forward先をしてい

ActionForm

アクションフォームは、@ActionFormアノテーションで指定

package jp.paulownia.test.action;
 
public class HogeAction {
    @ActionForm
    public HogeForm hogeForm;
}

アクションフォームクラスは ルートパッケージ以下のformパッケージに作成。命名規則はXxxxForm

package jp.paulownia.test.form;
 
public class HogeForm {
    @Required
    public String name;
}

注意:以下は古いやり方

入力パラメータはActionの中のpublicフィールドに入るので特にアクションフォームを作成する必要はない

public class HogeAction {
    public String name;     // パラメータでnameが送られてくるとココに入っている。
}

セッションスコープのActionFormが必要ならDTOを作成する

package jp.paulownia.test.action;
 
public class HogeAction {
    @ActionForm
    public HogeDto hogeDto;
}
package jp.paulownia.test.action;
 
@Component(instance = InstanceType.SESSION)
public class HogeDto implements Serializable {
    public String name;
}

フォームバリデーション

public class HogeAction {
    @Required
    public String id;     // パラメータでnameが送られてくるとココに入っている。
 
    @Execute(validation=false)   // このアクションメソッドではバリデーションしない
    public String list() {
        return "list.jsp";
    }
 
    @Execute(input="list.jsp")   // このアクションメソッドでは検査する。エラー時はlist.jspに戻る
    public String edit() {
        return "edit.jsp";
    }
}

セッションスコープにデータ格納

適当なDTOを作ってInstanceTypeをSESSIONにして、Actionクラスにフィールドを作っておくとコンテナが自動的にインスタンスをInjectしてくれます。

@Component(instance = InstanceType.SESSION)
public class FugaDto implements Serializable {
   private String value;
 
   ...
 
}

アクションクラスで

@Component(instance = InstanceType.SESSION)
public class FugaAction implements Serializable {
 
   @Resource
   private FugaDto fugaDto;
 
   ...
 
}

FugaDtoをpublicフィールドにすると、fuga/index?fugaDto=1 みたいなURLでアクセスするとDTOを上書きできてしまう(?)ので止めた方が良いという噂。

アプリケーションスコープにデータ格納

インスタンスのライフサイクルをAPPLICATIONにするだけ、あとはSessionと同じように使う

@Component(instance = InstanceType.APPLICATION)
public class PiyoDto implements Serializable {
   private String value;
   ...
}

アクションのユニットテスト

Seasar-user:13045

S2TestCaseではActionをテストクラスにインジェクションできないので、テストコード中でnewする。アクションの依存オブジェクト(サービスやJdbcManager)は、まずテストクラスにインジェクションして、アクションに手動でセットする。

public class HelloActionTest extends S2TestCase {
    public JdbcManager db;
 
    public FugaService fugaService;
 
    protected void setUp() throws Exception {
        include("app.dicon");
        super.setUp();
    }
 
    public void testIndex () {
        // テスト対象のアクションをnew
        HelloAction test = new HelloAction();
 
        // 依存クラスは自分でセット
        test.db = db;
        test.fugaService = fugaService;
 
        assertEquals("index.vm", test.index());
        assertEquals("Hello SAStruts Unit Test!", test.message);
        assertEquals(new SimpleDateFormat("yyyy-MM-dd").format(new Date()), test.today);
    }

俺インターセプタと俺アノテーションを作る

サンプルとして、アクションメソッドを起動できるHTTPメソッドを制限するインターセプタを作成する。

  • アクションメソッドにアノテーションで許可するHTTPメソッドを指定する。
  • 許可されないHTTPメソッドの場合、アクションメソッドを実行せずにHTTP Status 405を返す。

という仕様。

インターセプタクラス

package your.rootpackage.interceptor;
 
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
 
import org.aopalliance.intercept.MethodInvocation;
import org.seasar.framework.aop.interceptors.AbstractInterceptor;
import org.seasar.struts.util.RequestUtil;
import org.seasar.struts.util.ResponseUtil;
 
/**
 * SAStrutsのアクションメソッドの実行を、
 * 特定のHTTPメソッドによるアクセスの場合のみに許可するインターセプタです。
 * 許可されないHTTPメソッドでアクセスされた場合、HTTPステータス405を返します。
 *
 */
public class HttpMethodInterceptor extends AbstractInterceptor {
 
  /**
   * 許可するHTTPメソッド名、カンマ区切りで複数指定可。
   */
  public String value;
 
  @Override
  public Object invoke(MethodInvocation invocation) throws Throwable {    
    if (this.value != null) {
      HttpServletRequest request = RequestUtil.getRequest();
      String requestMethod = request.getMethod();
 
      String[] methods = this.value.split(",");
 
      for (String method: methods) {
        if (method.trim().equalsIgnoreCase(requestMethod)) {
          return invocation.proceed();
        }
      }
    }
 
    HttpServletResponse response = ResponseUtil.getResponse();
    response.setStatus(405);
    return null;
  }
}

アノテーション

package your.rootpackage.interceptor;
 
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
 
import org.seasar.framework.aop.annotation.Interceptor;
 
/**
 * {@link HttpMethodInterceptor}をSAStrutsのアクションメソッドに適用するアノテーションです。
 * 引数で許可するHTTPメソッドを指定します。カンマ区切りで複数のHTTPメソッドを指定できます。
 * 
 */
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
@Interceptor("httpMethodInterceptor")
public @interface HttpMethod {	
   String value();
}

使い方

public class AuthAction {
  @Execute(input = "index")
  @HttpMethod("post,get")
  public String login() {
    // 何か処理
  }
}
 
java/sastruts.txt · 最終更新: 2008/12/25 16:49 (外部編集)
 
特に明示されていない限り、本Wikiの内容は次のライセンスに従います:CC Attribution-Noncommercial-Share Alike 3.0 Unported
Recent changes RSS feed Donate Powered by PHP Valid XHTML 1.0 Valid CSS Driven by DokuWiki