読者です 読者をやめる 読者になる 読者になる

オレオレJava Webフレームワークを作ってみる。その1

以前から、Webフレームワークを妄想していたのですが、S2Utilが便利そうということでなんとなく作っています。
新しい発想はなく、色々、既存のフレームワークをパクってる感じです。。
以前の記事「いろんなJava Webフレームワークで同じ画面を作ってみる(Index) - よしなしごと」のようにサンプルを記載します。簡単な足し算画面です。とりあえずこのサンプルコードが動くレベルまではできてます。。

まずは、Actionクラスから

package webapp.action;

import org.selva2.webframework.ActionResult;
import org.selva2.webframework.RequestParams;
import org.selva2.webframework.annotation.Default;
import org.selva2.webframework.annotation.Event;
import org.selva2.webframework.annotation.IntegerType;
import org.selva2.webframework.annotation.Label;
import org.selva2.webframework.annotation.RequestScope;
import org.selva2.webframework.annotation.Required;
import static org.selva2.webframework.ActionUtil.*;

public class AddAction {

    public static class AddParams extends RequestParams {
        @Label("引かれる数")
        @Required
        @IntegerType
        public String arg1;

        @Label("引く数")
        @Required
        @IntegerType
        public String arg2;
    }

    @RequestScope
    public Integer result;

    @Default
    public ActionResult execute() {
        return forward("/WEB-INF/view/add/input.jsp");
    }

    @Event
    public ActionResult calculate(AddParams param) {
        if (param.isValidationError()) { // (1)
            return forward("/WEB-INF/view/add/input.jsp", param); // (2)
        }
        result = Integer.parseInt(param.arg1) + Integer.parseInt(param.arg2); // (3)
        return forward("/WEB-INF/view/add/result.jsp"); // (4)
    }
}

Actionクラスは、何かをextends, implementsしようかと思いましたが、結局POJO的になりました。

URLとアクションクラスの紐づき

URLとActionクラスは、規約により結びつきます。Actionクラスのメソッドには、結びつきません。
URL

http://localhost:8080/webapp/add

が、webapp.action.AddActionクラス に結びついてる感じです。
URLをカスタマイズする方法も妄想していますが、アノテーションでカスタマイズするのではなく、slim3みたいな設定クラスにしようかと思っています。そっちの方が、URLとクラスの紐づきが追いやすいかと。

リクエストパラメータの受け取り

内部クラスのAddParamsが、リクエストパラメータを受け取るクラスです。外部のクラスでも構いません。RequestParamsを継承します。
で、メソッドの引数で渡される感じです。

メソッドアノテーション

Default

通常コールされるメソッドを指定します。

Event

メソッド名称と同じ名前のリクエストパラメータが存在する場合、コールされます。サブミットボタンのname属性に対応する感じです。

フィールドアノテーション

Label

エラーメッセージに出力するラベル名称を指定します。langも以下の感じで指定可能。

@Label("ほげ", "ja")
@Label("hoge", "en")
public String hoge;

Labelアノテーションを指定しない場合、フィールド名称がラベル名称として扱われます。

Required, IntegerType

SAStrutsと同じ感じのバリデーション。

RequestScope

Actionメソッドが、コールされる前に、フィール名称でrequest.getAttributeされたオブジェクトがバインドされます。また、Actionメソッドがコールされた後に、request.setAttributeされます。デフォルトでフィールド名称が使われるが、以下のように変更することも可能

@RquestScope("FUGA")
public String hoge;

ActionResultクラス

メソッドの戻り値の型です。フォワード、リダイレクト等を指定します。
派生クラスで、Forward, Redirect, Json, Xmlとか。

その他

  • (1)でバリデーションエラーが発生してるかチェックします。エラー発生の画面遷移は、自動で行われず、コードで指定します。
  • (2)でフォワードしています。引数で、paramを渡していますが、これによりリクエストパラメータが、リクエストスコープに展開されます。バリデーションエラー時に、入力内容が消えないようにしています。
  • (3)ですが、StringをIntegerに変換しています。直接リクエストパラメータをIntegerで受け取れますが、最近リクエストパラメータは、Stringで受け取っておいた方が良いんじゃないかと考えいます。
  • (4)では、paramを渡していません。計算結果の画面には、入力内容を表示しないためです。return forwardView("/add/result");のように簡潔にかけるようにしようとも考えています。

次回は、設定ファイルとJSP