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はこの値を受け取ると、次の動作をします。
- 動作したActionクラスのuserフィールドを探す。
- userフィールドに定義したクラスのusernameフィールドを探して、Capybaraを格納する。
つまりActionクラスには、値を格納する親となるクラスを宣言し、そのフィールドを用意します。このフィールドに対してもValidationを定義するのが、VisitorFieldValidatorです。
VisitorFieldValidatorの定義
VisitorFieldValidatorを定義すると、Actionクラスから別のクラスへValidationの定義を移譲します。VisitorFieldValidatorの定義方法は以下のようになります。
@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の定義をします。
@Validations(
requiredFields = {
@RequiredFieldValidator(fieldName="username" , message="username.required" ) ,
} ,
)
@Data
public class SampleVO implements Serializable {
private String username;
private int age;
}
@Data,@Getter,@SetterはLombokのアノテーションです。
ModelDriven,ScopedModelDrivenとの相性
Struts2では、入力フィールドを別クラスへ格納するためのActionクラス用インタフェースにModelDriven,ScopedModelDrivenがあります。これらを使うと、別クラスのフィールドは model へ格納します。リクエストパラメータには接頭辞 model が不要になります。
ただし、ModelDrivenは何故かget/setメソッドの役割が逆転しているため、VisitorFieldValidatorとの相性は最悪です。使う場合はScopedModelDrivenを使わなければなりません。
また、フィールドは1つだけでなく複数のモデルとして格納したいケースがあるでしょう。その場合にはModelDrivenは適しません。