ひがやすを技術ブログ

電通国際情報サービスのプログラマ

Slim3 Strutsの仕様

Slim3 Strutsのベースは、SAStrutsですが、タイプセーフさをこれまでより目指したいと思っています。
例えば、SAStrutsのアクションでは、メソッド名を文字列で指定していました。

@Execute(reset = "reset", validate = "validate")
@Required(target = "login")

これを改善するために、まず、アクションの単位をユースケースではなく、SAStrutsでいっている実行メソッド単位にします。そして、アクション(実行メソッド)ごとにアクションフォームを指定できるようにします。
例えば、helloアプリケーションのsubmitメソッドは、次のようになります。

package tutorial.action.hello;

public class Submit extends S3Action {

    protected HelloForm form;

    @Override
    public ActionForward execute() {
        ...
    }
}

executeメソッドは、S3Actionでabstract定義されているので、正確にオーバーライドしないとコンパイルエラーになります。アクションフォームをキャストする必要がないのがポイント。
S3Actionはこんな感じ。

public class S3Action extends Action {
    @Override
    public ActionForward execute(
        ActionMapping mapping,
        ActionForm form,
        HttpServletRequest request,
        HttpServletResponse response)
        throws Exception {
        this.request = request;
        this.response = response;
        formField.set(this, form);
        return execute();
    }

    public abstract ActionForward execute() throws Exception;

アクションフォームは次のようになります。

package tutorial.action.hello;

public class SubmitForm extends S3ActionForm {

    ...
}

リセットメソッドと検証メソッドは、S3ActionFormで次のように定義されています。

public class S3ActionForm extends ActionForm {
    @Override
    public final void reset(ActionMapping mapping, HttpServletRequest request) {
        this.request = request;
        reset();
    }

    public void reset() {
    }

    @Override
    public final ActionErrors validate(ActionMapping mapping, HttpServletRequest request) {
        this.request = request;
        return validate();
    }

    public ActionErrors validate() {
        return null;
    }
}

メソッドをオーバーライドしたときは、@Overrideが必要(IDEの設定しだいだけど)なので、スペルミスにも直ぐ気付きます。


URLとアクションクラスのマッピングは次のとおり。
URLが/で終わっている場合は、IndexActionにマッピングする。/で終わっていない場合は、URLの/の直後を大文字にしてActionをつける。
例えば、/hello/は、tutorial.action.hello.IndexActionにマッピングされ、/hello/submitは、tutorial.action.hello.SubmitActionにマッピングされます。


フォワードとリダイレクトは、次のような感じ。forwardとredirectは、S3Actionのメソッドです。

public class HogeAction extends S3Action {

    @Override
    public ActionForward execute() {
        return forward("hoge.jsp");
    }
}
public class HogeAction extends S3Action {

    @Override
    public ActionForward execute() {
        return redirect("http://www.slim3.org/");
    }
}

他のアクションに遷移するには次のようにクラスリテラルが使えます。

public class HogeAction extends S3Action {

    @Override
    public ActionForward execute() {
        return redirect(IndexAction.class);
    }
}


アクションとアクションフォームの単位が、オリジナルのStrutsと同じなので、理解しやすいんじゃないかと思います。
設定ファイルはもちろん必要ないですよ。当然HOT deployもできます。


迷っているのは、アクションの単位は、これまでと同じユースケースで、実行メソッドごとに引数でアクションフォームを指定する方法との優劣。

public class HelloAction extends S3Action {

    @Execute
    public ActionForward index() {
        return forward("index.jsp");
    }

    @Execute
    public ActionForward submit(HelloForm form) {
        return forward("index.jsp");
    }
}

こっちの方法のほうが、クラス数もソースの行数も少なくなりますが、タイプセーフ性が弱くなります。妥協できる範囲内だとは思ってますが。
ご意見をお聞かせてもらえれば、幸いです。


Slim3 Strutsは、コンテナに依存しないので、Spring、GuiceEJB3コンテナと組み合わせることもできます。Slim3以外のコンテナを使った場合は、HOT deployが使えなくなりますが、それ以外の制限は特にありません。