内容へ移動
Cat Paw Software
ユーザ用ツール
ログイン
サイト用ツール
検索
ツール
文書の表示
以前のリビジョン
バックリンク
最近の変更
メディアマネージャー
サイトマップ
ログイン
>
最近の変更
メディアマネージャー
サイトマップ
トレース:
java:sastruts
この文書は読取専用です。文書のソースを閲覧することは可能ですが、変更はできません。もし変更したい場合は管理者に連絡してください。
====== Super Agile Struts (SAStruts) ====== [[http://sastruts.seasar.org/|SAStruts]]はSeasarプロジェクトのWebフレームワーク。ActionやFormの扱いがStrutsとは大きく違うため、Struts上に作った別のフレームワークと考えると良いかもしれない。 バリデーションや画面遷移をアノテーションで指定出来るため、Struts特有の設定ファイルが要らずコードに集中でき書きやすい。 ===== 使ってみる ===== EclipseとDoltengプラグインを使ってSAStrutsのプロジェクトを作る。パッケージ名だけ最初に決める必要がある。 ===== 基本的な使い方 ===== ActionはタダのJava Object (POJO) でStruts Actionクラスを継承する必要は無い。 <code java> 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"; } } </code> というアクションがある場合、 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 <code java> package jp.paulownia.test.action.fuga; public class HigeAction { @Execute(validation=false) public String edit() { return "edit.jsp"; } } </code> 遷移先を指定する戻り値とinputの値はjsp名、またはアクションメソッド名。forward先をしてい ===== ActionForm ===== アクションフォームは、@ActionFormアノテーションで指定 <code java> package jp.paulownia.test.action; public class HogeAction { @ActionForm public HogeForm hogeForm; } </code> アクションフォームクラスは ルートパッケージ以下のformパッケージに作成。命名規則は''XxxxForm''。 <code java> package jp.paulownia.test.form; public class HogeForm { @Required public String name; } </code> 注意:以下は古いやり方 入力パラメータはActionの中のpublicフィールドに入るので特にアクションフォームを作成する必要はない <code java> public class HogeAction { public String name; // パラメータでnameが送られてくるとココに入っている。 } </code> セッションスコープのActionFormが必要ならDTOを作成する <code java> package jp.paulownia.test.action; public class HogeAction { @ActionForm public HogeDto hogeDto; } </code> <code java> package jp.paulownia.test.action; @Component(instance = InstanceType.SESSION) public class HogeDto implements Serializable { public String name; } </code> ===== フォームバリデーション ===== <code java> 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"; } } </code> ===== セッションスコープにデータ格納 ===== 適当なDTOを作ってInstanceTypeをSESSIONにして、Actionクラスにフィールドを作っておくとコンテナが自動的にインスタンスをInjectしてくれます。 <code java> @Component(instance = InstanceType.SESSION) public class FugaDto implements Serializable { private String value; ... } </code> アクションクラスで <code java> @Component(instance = InstanceType.SESSION) public class FugaAction implements Serializable { @Resource private FugaDto fugaDto; ... } </code> FugaDtoをpublicフィールドにすると、fuga/index?fugaDto=1 みたいなURLでアクセスするとDTOを上書きできてしまう(?)ので止めた方が良いという噂。 ===== アプリケーションスコープにデータ格納 ===== インスタンスのライフサイクルをAPPLICATIONにするだけ、あとはSessionと同じように使う <code java> @Component(instance = InstanceType.APPLICATION) public class PiyoDto implements Serializable { private String value; ... } </code> ===== アクションのユニットテスト ===== [[http://ml.seasar.org/archives/seasar-user/2008-February/013045.html|Seasar-user:13045]] S2TestCaseではActionをテストクラスにインジェクションできないので、テストコード中でnewする。アクションの依存オブジェクト(サービスやJdbcManager)は、まずテストクラスにインジェクションして、アクションに手動でセットする。 <code java> 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); } </code> ===== 俺インターセプタと俺アノテーションを作る ===== サンプルとして、アクションメソッドを起動できるHTTPメソッドを制限するインターセプタを作成する。 * アクションメソッドにアノテーションで許可するHTTPメソッドを指定する。 * 許可されないHTTPメソッドの場合、アクションメソッドを実行せずにHTTP Status 405を返す。 という仕様。 インターセプタクラス <code java> 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; } } </code> アノテーション <code java> 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(); } </code> 使い方 <code java> public class AuthAction { @Execute(input = "index") @HttpMethod("post,get") public String login() { // 何か処理 } } </code> ===== JNDIのデータソース設定を使う ===== SAStruts 1.0.4 sp8 jdbc.diconの設定を以下のようにする <code xml> <?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE components PUBLIC "-//SEASAR2.1//DTD S2Container//EN" "http://www.seasar.org/dtd/components21.dtd"> <components namespace="jdbc"> <include path="jta.dicon"/> <component name="xaDataSource" class="org.seasar.extension.dbcp.impl.DataSourceXADataSource"> <property name="dataSourceName">"java:comp/env/jdbc/hogehoge"</property> </component> <component name="connectionPool" class="org.seasar.extension.dbcp.impl.ConnectionPoolImpl"> <property name="timeout">600</property> <property name="maxPoolSize">10</property> <property name="allowLocalTx">true</property> <destroyMethod name="close"/> </component> <component name="DataSource" class="org.seasar.extension.dbcp.impl.DataSourceImpl" /> </components> </code> jdbc/hogehogeという名前でJNDIにデータソースを登録しておく、context.xmlに書くならば <code xml> <?xml version="1.0" encoding="UTF-8"?> <Context path="/contextName" reloadable="false" docBase="contextName"> <Resource auth="Container" type="javax.sql.DataSource" name="jdbc/hogehoge" driverClassName="com.mysql.jdbc.Driver" url="jdbc:mysql://localhost:3306/hogehoge?characterEncoding=UTF-8&amp;characterSetResults=UTF-8" username="hoge" password="hoge" maxActive="4" maxIdle="1" defaultAutoCommit="false" validationQuery="SELECT 1" testWhileIdle="true" minEvictableIdleTimeMillis="180000" /> </Context> </code> ===== 複数のデータソースを使う ===== jdbc.diconを2つコピーする。 * jdbc1.dicon - 一つ目のDBの設定 * jdbc2.dicon - 二つ目のDBの設定 * jdbc.dicon - 不要なので削除する s2jdbc.diconを2つコピーする。 * s2jdbc1.dicon - 一つ目のDBに接続するJDBCManagerの設定、jdbc.diconの代わりにjdbc1.diconをインクルードする * s2jdbc2.dicon - 二つ目のDBに接続するJDBCManagerの設定、jdbc.diconの代わりにjdbc2.diconをインクルードする * s2jdbc.dicon - JDBCManagerの設定は削除し、上記2つのdiconをincludeするだけ
java/sastruts.txt
· 最終更新:
2010/11/15 06:26
by
127.0.0.1
ページ用ツール
文書の表示
以前のリビジョン
バックリンク
文書の先頭へ