LoginSignup
6
6

More than 5 years have passed since last update.

Struts2のActionクラスから別のクラスへValidationを定義する

Last updated at Posted at 2014-09-30

ActionクラスとValidationの関係

Struts2の入力値検証、Validationの機能はActionクラスに対して定義します。
設定内容はxmlで記載するか、アノテーションで記載するかのどちらかを選べます。
ここではアノテーションベースのValidation定義の方法ならびに、Actionクラス以外にValidationを定義する方法を紹介します。

ActionクラスにValidationを定義したときの振る舞い

Actionクラスは、リクエストパラメータの値をActionクラスのフィールドへ格納しようと試みます。この時にValidationの定義がある場合は、Actionクラスのメソッドを実行する前にValidationが実行されます。

もしValidationの結果、なんらかの入力チェックに引っかかった場合はActionクラスのメソッドが実行されずに、Actionクラスは"input"(ActionSupport.INPUT)の値をreturnします。
※このinputへ戻す動きは、Struts2標準インターセプタの workflowインターセプタによって制御されています。

そのため、Actionクラスのresultに"input"(ActionSupport.INPUT)の値が定義されていない、または継承したパッケージにも未定義である場合は、「resultの値に input が定義されてないよ(´・ω・`)?」となり、実行時の例外となってスタックトレースを含んだエラー画面を出力します。

Actionクラスと入力フィールドの関係

Struts2はOGNLを利用して、リクエストパラメータをActionクラスのフィールドへ自動変換します。これにより、リクエストパラメータは次のことが可能です。

  • オブジェクトの階層をピリオドで表現できる
  • 配列の操作も可能

例えば、画面から送信されたリクエストパラメータが次の値になっているとします。

user.username=Capybara

Struts2はこの値を受け取ると、次の動作をします。

  1. 動作したActionクラスのuserフィールドを探す。
  2. userフィールドに定義したクラスのusernameフィールドを探して、Capybaraを格納する。

つまりActionクラスには、値を格納する親となるクラスを宣言し、そのフィールドを用意します。このフィールドに対してもValidationを定義するのが、VisitorFieldValidatorです。

VisitorFieldValidatorの定義

VisitorFieldValidatorを定義すると、Actionクラスから別のクラスへValidationの定義を移譲します。VisitorFieldValidatorの定義方法は以下のようになります。

SampleSubscribeAction.java

@Validations(
    visitorFields = {
        @VisitorFieldValidator(fieldName="vo" , appendPrefix=true)
    }
)
public class SampleSubscribeAction extends ActionSupport {
    @Action("subscribe")
    public String subscribe() throws Exception {
        return SUCCESS;
    }

    @Getter @Setter
    private SampleVO vo;
}

アノテーション@VisitorFieldValidatorにて、どのフィールドのクラスに移譲するかを定義しました。以下の属性を設定します。

属性名 概要
fieldName VisitorFieldValidatorの対象となるActionクラスのフィールド名
appendPrefix trueにすると、エラー時の項目名にActionクラスのフィールド名を接頭辞につけます。

上記の例の場合、項目エラーがあった場合の項目名は「vo.」で始まります。
移譲される側のクラスは、入力項目に対するフィールドとValidationの定義が可能です。

移譲される側のクラス

移譲される側のクラスは、入力項目のフィールドとValidationの定義をします。

SampleVO.java
@Validations(
    requiredFields = {
        @RequiredFieldValidator(fieldName="username" , message="username.required" ) ,
    } ,
)
@Data
public class SampleVO implements Serializable {
    private String username;
    private int age;
}

@Data,@Getter,@SetterLombokのアノテーションです。

ModelDriven,ScopedModelDrivenとの相性

Struts2では、入力フィールドを別クラスへ格納するためのActionクラス用インタフェースにModelDriven,ScopedModelDrivenがあります。これらを使うと、別クラスのフィールドは model へ格納します。リクエストパラメータには接頭辞 model が不要になります。
ただし、ModelDrivenは何故かget/setメソッドの役割が逆転しているため、VisitorFieldValidatorとの相性は最悪です。使う場合はScopedModelDrivenを使わなければなりません。
また、フィールドは1つだけでなく複数のモデルとして格納したいケースがあるでしょう。その場合にはModelDrivenは適しません。

6
6
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
6
6