Struts2 Validation

# 概要
Struts2のValidationフレームワークについて
調査対象：struts-6.0.0-SNAPSHOT

# Validationの定義方法
Validationの定義方法はXMLとアノテーションの2種類あり、両方使うことも可能。
- XML
<dl><dd>
検証内容を*-validation.xmlファイルに記述する。*-validation.xmlの「*」にはアクションクラス名を指定し、アクションクラスと同じフォルダに作成するか、resourceフォルダになどにアクションクラスと同じパッケージ構成で配置する。
*-validation.xmlはアクションが実装しているインターフェース、親クラスも対象となるためそちらで定義してもよい。
<details><summary>対象となるvalidation.xml</summary>
<table>
<thead>
<th>#</th>
<th>パス</th>
<th>例</th>
</thead>
<tbody>
<tr>
<td>1</td>
<td>java/lang/Object-validation.xml</td>
<td></td>
</tr>
<tr>
<td>2</td>
<td>java/lang/Object-アクション名-validation.xml</td>
<td>java/lang/Object-hello-validation.xml</td>
</tr>
<tr>
<td>3</td>
<td>Actionクラスの親クラスが実装しているインターフェイス-validation.xml　※</td>
<td>com/action/BaseAction-Interface1-validation.xml</td>
</tr>
<tr>
<td>4</td>
<td>Actionクラスの親クラスが実装しているインターフェイス-アクション名-validation.xml　※</td>
<td>com/action/BaseAction-Interface1-hello-validation.xml</td>
</tr>
<tr>
<td>5</td>
<td>Actionクラスの親クラス-validation.xml　※</td>
<td>com/action/BaseAction-validation.xml</td>
</tr>
<tr>
<td>6</td>
<td>Actionクラスの親クラス-アクション名-validation.xml　※</td>
<td>com/action/BaseAction-hello-validation.xml</td>
</tr>
<tr>
<td>7</td>
<td>Actionクラスが実装しているインターフェイス-validation.xml</td>
<td>com/action/HelloAction-Interface1-validation.xml</td>
</tr>
<tr>
<td>8</td>
<td>Actionクラスが実装しているインターフェイス-アクション名-validation.xml</td>
<td>com/action/HelloAction-Interface1-hello-validation.xml</td>
</tr>
<tr>
<td>9</td>
<td>Actionクラス-validation.xml</td>
<td>com/action/HelloAction-validation.xml</td>
</tr>
<tr>
<td>10</td>
<td>Actionクラス-myContext-validation.xml</td>
<td>com/action/HelloAction-hello-validation.xml</td>
</tr>
</tbody>
</table>
※Objectクラスに到達するまで繰り返す。
</details>

validation.xmlの記述方法はField ValidatorシンタックスとPlain Validatorシンタックスの2種類があり、どちらで書いてもよい。
- Field Validatorシンタックス
```xml
<validators>
    <field name="...(必須)">
        <field-validator type="...(必須)" short-circuit="(true|false(デフォルト))">
            <params name="...(必須)">...</params>
            <message key="...">...</message>
        </field-validator>
    </field>
</validators>
```
- Plain Validatorシンタックス
```xml
<validators>
    <validator type="...(必須)" short-circuit="(true|false(デフォルト))">
        <param name="...(必須)">...</params>
        <message key="...">...</message>
    </validator>
</validators>
```

</dd></dl>

- アノテーション
<dl><dd>
class、メソッド（getter、setter、アクションメソッドなど）にValidatorのアノテーションを付与する。classに付与できるのはCustomValidatorとValidationsのみ。それ以外はメソッドに付与する。

```java
@CustomValidator(type="...")
@Validations(...)
public class xxxxAction {

    @xxxValidator(message = "...", key = "...", shortCircuit = true)
    public String getUserName() {
        return this.username;
    }

    @xxxValidator(message = "...", key = "...", shortCircuit = true)
    public String execute() {
    }
}
```
</dd></dl>

# 組み込みのValidator
| クラス| タイプ| 機能 |対象|
|:--|:--|:--|:--|
|[RequiredFieldValidator](#requiredfieldvalidator)|required|指定したフィールドがnot nullであることを検証する。|フィールド|
|[RequiredStringValidator](#requiredstringvalidator)|requiredstring|指定したフィールドがnot nullかつ長さが0より大きいことを検証する。|フィールド|
|[IntRangeFieldValidator](#intrangefieldvalidator)|int|int型数値が指定した値の範囲内であること|フィールド|
|[LongRangeFieldValidator](#longrangefieldvalidator)|long|long型数値が指定した値の範囲内であること|フィールド|
|[ShortRangeFieldValidator](#shortrangefieldvalidator)|short|short型数値が指定した値の範囲内であること|フィールド|
|[DoubleRangeFieldValidator](#doublerangefieldvalidator)|double|double型数値が指定した値の範囲内であること|フィールド|
|[DateRangeFieldValidator](#daterangefieldvalidator)|date|日付が指定した値の範囲内であること|フィールド|
|[ExpressionValidator](#expressionvalidator)|expression|OGNL式を評価しfalseであればエラー。特定のフィールドに依らないアクションレベルの検証|
|[FieldExpressionValidator](#fieldexpressionvalidator)|fieldexpression|OGNL式を評価しfalseであればエラー。特定のフィールドが対象|フィールド|
|[EmailValidator](#emailvalidator)|email|有効なemailアドレスであること|フィールド|
|[CreditCardValidator](#creditcardvalidator)|creditcard|有効なクレジットカード番号であること|フィールド|
|[URLValidator](#urlvalidator)|url|有効なURLであること|フィールド|
|[VisitorFieldValidator](#visitorfieldvalidator)|visitor|フィールドの型に定義されたvalidation定義によって検証する|フィールド|
|[ConversionErrorFieldValidator](#conversionerrorfieldvalidator)|conversion|型変換エラー（Integer型のフィールドにoneを指定するなど）が起きているか検証する。※ConversionErrorInterceptorが同等の処理を実施するのでその場合は使わなくてよい。|フィールド|
|[StringLengthFieldValidator](#stringlengthfieldvalidator)|stringlength|文字列の長さが指定した値の範囲内であること|フィールド|
|[RegexFieldValidator](#regexfieldvalidator)|regex|正規表現にマッチすること|フィールド|
|[ConditionalVisitorFieldValidator](#conditionalvisitorfieldvalidator)|conditionalvisitor|条件に合致したときVisitorFieldValidatorを呼び出す。|フィールド|

## 共通のパラメータ
各種Validatorに共通するパラメータを以下に記す。
- XML

| 属性| 意味|
|:--|:--|
|message|エラーメッセージ。&lt;message&gt;を記述することで指定する。※詳細は[後述](https://qiita.com/tm777/items/0dd91fd0ac82b2530f0d#xml%E3%81%AB%E3%81%8A%E3%81%91%E3%82%8Bmessage%E3%81%AE%E6%9B%B8%E3%81%8D%E6%96%B9)|
|fieldName|対象のフィールド。&lt;param name="fieldName"&gt;を記述することで指定する。<br/>※Plain Validatorシンタックス（&lt;validator type="..."&gt;）の場合のみ必要|
|shortCircuit|trueの場合short-circuit（エラーがあればそれ以降の検証を行わない。）<br/>※&lt;validator&gt;、&lt;field-validator&gt;にshort-circuit属性として指定する|

- アノテーション

| 属性| 意味|
|:--|:--|
|message|既定のエラーメッセージ。keyに有効な値が指定された場合は無視される。|
|key|国際化対応(i18n)のメッセージをpropertiesファイルから取得するキー|
|messageParams|上記メッセージに埋め込む文字列の配列|
|fieldName ※1|下記のValidatorタイプにSIMPLEを指定した場合に検証対象のフィールド名を指定する|
|shortCircuit|trueの場合short-circuit（エラーがあればそれ以降の検証を行わない。）|
|type ※2|フィールド／メソッドに対するValidationタイプ。ValidatorType.FIELD／ValidatorType.SIMPLEのいずれかを指定する。検証対象のフィールドに直接Validatorのアノテーションを指定する場合はValidatorType.FIELD、アクションメソッドに@Validationsアノテーションを指定して一括でValidatorのアノテーションを指定する場合はValidatorType.SIMPLEを指定する。どちらを指定しても処理に違いはない。|

※1 ExpressionValidatorは無し
※2 ExpressionValidator／FieldExpressionValidator／VisitorFieldValidator／ConditionalVisitorFieldValidatorは無し

## RequiredFieldValidator
<dl>
  <dt>機能</dt>
  <dd>指定したフィールドがnot nullであることを検証する。JSPで&lt;s:textfield>などのname属性に指定したフィールドは未入力の場合に""になるのでこのValidatorではエラーにならない。代わりにRequiredStringValidatorを使用する。<br/><br/></dd>
  <dt>パラメータ</dt>
  <dd>なし<br/><br/></dd>
  <dt>使用例</dt>
  <dd>
<details><summary>XML</summary>

```xml
<!DOCTYPE validators PUBLIC "-//Apache Struts//XWork Validator 1.0.3//EN"
		"http://struts.apache.org/dtds/xwork-validator-1.0.3.dtd">
<validators>
    <!-- Field Validator Syntax -->
    <field name="username">
        <field-validator type="required">
            <message>username must not be null</message>
        </field-validator>
    </field>
    <!-- Plain Validator Syntax -->
    <validator type="required">
        <param name="fieldName">username</param>
        <message>username must not be null</message>
    </validator>
</validators>
```
</details>
<details><summary>アノテーション</summary>

```java
    @RequiredFieldValidator(message = "Default message", key = "i18n.key", shortCircuit = true)
    public String getUserName() {
        return this.username;
    }
```
</details>
</dd>
</dl>

## RequiredStringValidator
<dl>
  <dt>機能</dt>
  <dd>指定したフィールドがnot nullかつ長さが0より大きいことを検証する。<br/><br/></dd>
  <dt>パラメータ</dt>
  <dd>

|名前|意味|既定値|
|--|--|--|
|trim|長さを調べる前に前後の空白を除去するかどうか|true|
|trimExpression|trimパラメータを${...}形式のOGNL式で指定する。<br/>※自宅の環境ではTextParseUtil.javaの167行目で「java.lang.NullPointerException: Cannot invoke "com.opensymphony.xwork2.util.ValueStack.getActionContext()" because "stack" is null」が発生しうまくいかなかった。|-|

</dd>
  <dt>使用例</dt>
  <dd>
<details><summary>XML</summary>

```xml
<!DOCTYPE validators PUBLIC "-//Apache Struts//XWork Validator 1.0.3//EN"
		"http://struts.apache.org/dtds/xwork-validator-1.0.3.dtd">
<validators>
    <!-- Plain-Validator Syntax -->
    <validator type="requiredstring">
        <param name="fieldName">username</param>
        <param name="trim">true</param>
        <message>username is required</message>
    </validator>

    <!-- Field-Validator Syntax -->
    <field name="username">
        <field-validator type="requiredstring">
            <param name="trim">true</param>
            <message>username is required</message>
        </field-validator>
    </field>

    <!-- Field-Validator Syntax with expression -->
    <field name="username">
        <field-validator type="requiredstring">
            <param name="trimExpression">${trimValue}</param> <!-- will be evaluated as: boolean getTrimValue() -->
            <message>username is required</message>
        </field-validator>
    </field>
</validators>
```
</details>
<details><summary>アノテーション</summary>

```java
    @RequiredStringValidator(message = "Default message", key = "i18n.key", shortCircuit = true, trim = true)
    public String getUserName() {
        return this.username;
    }
```
</details>
</dd>
</dl>

## IntRangeFieldValidator
<dl>
  <dt>機能</dt>
  <dd>int型の数値が指定した値の範囲内であるか検証する。min／maxとminExpression／maxExpressionの両方を指定した場合はmin／maxが優先される。以下であればエラーなしと判定する。<br/>
(min or minExpression) ≦ フィールドの値 ≦ (max or maxExpression)<br/><br/></dd>
  <dt>パラメータ</dt>
  <dd>

|名前|意味|既定値|
|--|--|--|
|min|最小値|null|
|max|最大値|null|
|minExpression|最小値を算出するための${...}形式のOGNL式|null|
|maxExpression|最大値を算出するための${...}形式のOGNL式|null|

※パラメータを設定しなかった項目については検証を行わない。<br/><br/>
</dd>
  <dt>使用例</dt>
  <dd>
<details><summary>XML</summary>

```xml
<!DOCTYPE validators PUBLIC "-//Apache Struts//XWork Validator 1.0.3//EN"
		"http://struts.apache.org/dtds/xwork-validator-1.0.3.dtd">
<validators>
     <!-- Plain Validator Syntax -->
     <validator type="int">
         <param name="fieldName">age</param>
         <param name="min">20</param>
         <param name="max">50</param>
         <message>Age needs to be between ${min} and ${max}</message>
     </validator>

     <!-- Field Validator Syntax -->
     <field name="age">
         <field-validator type="int">
             <param name="min">20</param>
             <param name="max">50</param>
             <message>Age needs to be between ${min} and ${max}</message>
         </field-validator>
     </field>

     <!-- Field Validator Syntax with expression -->
     <field name="age">
         <field-validator type="int">
             <param name="minExpression">${minValue}</param> <!-- will be evaluated as: Integer getMinValue() -->
             <param name="maxExpression">${maxValue}</param> <!-- will be evaluated as: Integer getMaxValue() -->
             <message>Age needs to be between ${min} and ${max}</message>
         </field-validator>
     </field>
</validators>
```
</details>
<details><summary>アノテーション</summary>

```java
    @IntRangeFieldValidator(message = "Default message", key = "i18n.key", shortCircuit = true, min = "0", max = "42")
    public int getNumber() {
        return this.number;
    }
 
    @IntRangeFieldValidator(message = "Default message", key = "i18n.key", shortCircuit = true, minExpression = "${minValue}", maxExpression = "${maxValue}")
    public int getNumber() {
        return this.number;
    }
```
</details>
</dd>
</dl>

## LongRangeFieldValidator
<dl>
  <dt>機能</dt>
  <dd>long型の数値が指定した値の範囲内であるか検証する。min／maxとminExpression／maxExpressionの両方を指定した場合はmin／maxが優先される。以下であればエラーなしと判定する。<br/>
(min or minExpression) ≦ フィールドの値 ≦ (max or maxExpression)<br/><br/></dd>
  <dt>パラメータ</dt>
  <dd>

|名前|意味|既定値|
|--|--|--|
|min|最小値|null|
|max|最大値|null|
|minExpression|最小値を算出するための${...}形式のOGNL式|null|
|maxExpression|最大値を算出するための${...}形式のOGNL式|null|

※パラメータを設定しなかった項目については検証を行わない。<br/><br/>
</dd>
  <dt>使用例</dt>
  <dd>
<details><summary>XML</summary>

```xml
<!DOCTYPE validators PUBLIC "-//Apache Struts//XWork Validator 1.0.3//EN"
		"http://struts.apache.org/dtds/xwork-validator-1.0.3.dtd">
<validators>
    <!-- Plain Validator Syntax -->
    <validator type="long">
        <param name="fieldName">age</param>
        <param name="min">20</param>
        <param name="max">50</param>
        <message>Age needs to be between ${min} and ${max}</message>
    </validator>

    <!-- Field Validator Syntax -->
    <field name="age">
        <field-validator type="long">
            <param name="min">20</param>
            <param name="max">50</param>
            <message>Age needs to be between ${min} and ${max}</message>
        </field-validator>
    </field>

    <!-- Field Validator Syntax with expression -->
    <field name="age">
        <field-validator type="long">
            <param name="minExpression">${minValue}</param> <!-- will be evaluated as: Long getMinValue() -->
            <param name="maxExpression">${maxValue}</param> <!-- will be evaluated as: Long getMaxValue() -->
            <message>Age needs to be between ${min} and ${max}</message>
        </field-validator>
    </field>
</validators>
```
</details>
<details><summary>アノテーション</summary>

```java
    @LongRangeFieldValidator(message = "Default message", key = "i18n.key", shortCircuit = true, min = "0", max = "42")
    public long getNumber() {
        return this.number;
    }

    @LongRangeFieldValidator(message = "Default message", key = "i18n.key", shortCircuit = true, minExpression = "${minValue}", maxExpression = "${maxValue}")
    public long getNumber() {
        return this.number;
    }
```
</details>
</dd>
</dl>

## ShortRangeFieldValidator
<dl>
  <dt>機能</dt>
  <dd>short型の数値が指定した値の範囲内であるか検証する。min／maxとminExpression／maxExpressionの両方を指定した場合はmin／maxが優先される。以下であればエラーなしと判定する。<br/>
(min or minExpression) ≦ フィールドの値 ≦ (max or maxExpression)<br/><br/></dd>
  <dt>パラメータ</dt>
  <dd>

|名前|意味|既定値|
|--|--|--|
|min|最小値|null|
|max|最大値|null|
|minExpression|最小値を算出するための${...}形式のOGNL式|null|
|maxExpression|最大値を算出するための${...}形式のOGNL式|null|

※パラメータを設定しなかった項目については検証を行わない。<br/><br/>
</dd>
  <dt>使用例</dt>
  <dd>
<details><summary>XML</summary>

```xml
<!DOCTYPE validators PUBLIC "-//Apache Struts//XWork Validator 1.0.3//EN"
		"http://struts.apache.org/dtds/xwork-validator-1.0.3.dtd">
<validators>
    <!-- Plain Validator Syntax -->
    <validator type="short">
        <param name="fieldName">age</param>
        <param name="min">20</param>
        <param name="max">50</param>
        <message>Age needs to be between ${min} and ${max}</message>
    </validator>

    <!-- Field Validator Syntax -->
    <field name="age">
        <field-validator type="short">
            <param name="min">20</param>
            <param name="max">50</param>
            <message>Age needs to be between ${min} and ${max}</message>
        </field-validator>
    </field>

    <!-- Field Validator Syntax with expression -->
    <field name="age">
        <field-validator type="short">
            <param name="minExpression">${minValue}</param> <!-- will be evaluated as: Short getMinValue() -->
            <param name="maxExpression">${maxValue}</param> <!-- will be evaluated as: Short getMaxValue() -->
            <message>Age needs to be between ${min} and ${max}</message>
        </field-validator>
    </field>
</validators>
```
</details>
<details><summary>アノテーション</summary>

```java
    @ShortRangeFieldValidator(message = "Default message", key = "i18n.key", shortCircuit = true, min = "0", max = "42")
    public short getNumber() {
        return this.number;
    }

    @ShortRangeFieldValidator(message = "Default message", key = "i18n.key", shortCircuit = true, min = "${minValue}", max = "${maxValue}")
    public short getNumber() {
        return this.number;
    }

```
</details>
</dd>
</dl>

## DoubleRangeFieldValidator
<dl>
  <dt>機能</dt>
  <dd>double型の数値が指定した値の範囲内であるか検証する。値を指定するパラメータとOGNL式で指定するパラメータがあり、両方指定した場合は値を指定したパラメータが優先される。以下であればエラーなしと判定する。<br/>
(minInclusive or minInclusiveExpression) ≦ フィールドの値 ≦ (maxInclusive or maxInclusiveExpression)、かつ<br/>
(minExclusive or minExclusiveExpression) ＜ フィールドの値 ＜ (maxExclusive or maxExclusiveExpression)<br/><br/></dd>
  <dt>パラメータ</dt>
  <dd>

|名前|意味|既定値|
|--|--|--|
|minInclusive|最小値|null|
|maxInclusive|最大値|null|
|minExclusive|最小値（範囲には含まない）|null|
|maxExclusive|最大値（範囲には含まない）|null|
|minInclusiveExpression|最小値を算出するための${...}形式のOGNL式|null|
|maxInclusiveExpression|最大値を算出するための${...}形式のOGNL式|null|
|minExclusiveExpression|最小値（範囲には含まない）を算出するための${...}形式のOGNL式|null|
|maxExclusiveExpression|最大値（範囲には含まない）を算出するための${...}形式のOGNL式|null|

※パラメータを設定しなかった項目については検証を行わない。<br/><br/>
</dd>
  <dt>使用例</dt>
  <dd>
<details><summary>XML</summary>

```xml
<!DOCTYPE validators PUBLIC "-//Apache Struts//XWork Validator 1.0.3//EN"
		"http://struts.apache.org/dtds/xwork-validator-1.0.3.dtd">
<validators>
    <!-- Plain Validator Syntax -->
    <validator type="double">
        <param name="fieldName">percentage</param>
        <param name="minInclusive">20.1</param>
        <param name="maxInclusive">50.1</param>
        <message>Age needs to be between ${minInclusive} and ${maxInclusive} (inclusive)</message>
    </validator>

    <!-- Field Validator Syntax -->
    <field name="percentage">
        <field-validator type="double">
            <param name="minExclusive">0.123</param>
            <param name="maxExclusive">99.98</param>
            <message>Percentage needs to be between ${minExclusive} and ${maxExclusive} (exclusive)</message>
        </field-validator>
    </field>

    <!-- Field Validator Syntax with expression -->
    <field name="percentage">
        <field-validator type="double">
            <param name="minExclusiveExpression">${minExclusiveValue}</param> <!-- will be evaluated as: Double getMinExclusiveValue() -->
            <param name="maxExclusiveExpression">${maxExclusiveValue}</param> <!-- will be evaluated as: Double getMaxExclusiveValue() -->
            <message>Percentage needs to be between ${minExclusive} and ${maxExclusive} (exclusive)</message>
        </field-validator>
    </field>
</validators>
```
</details>
<details><summary>アノテーション</summary>

```java
    @DoubleRangeFieldValidator(message = "Default message", key = "i18n.key", shortCircuit = true, minInclusive = "0.123", maxInclusive = "99.987")
    public Double getNumber() {
        return this.number;
    }
```
</details>
</dd>
</dl>

## DateRangeFieldValidator
<dl>
  <dt>機能</dt>
  <dd>日付が指定した値の範囲内であるか検証する。min／maxとminExpression／maxExpressionの両方を指定した場合はmin／maxが優先される。以下であればエラーなしと判定する。<br/>
(min or minExpression) ≦ フィールドの値 ≦ (max or maxExpression)<br/>
<br/>
日付の形式はロケールによって異なるがjaの場合は以下のいずれか
<ul>
<li>y/MM/dd H<span>:</span>mm:ss z</li>
<li>y/MM/dd H<span>:</span>mm:ss</li>
<li>y/MM/dd H:mm</li>
<li>y/MM/dd</li>
<li>y年M月d日</li>
<li>yyyy-MM-dd</li>
<li>yyyy-MM-dd'T'HH<span>:</span>mm:ss</li>
</ul>
上記はpropertiesファイルにstruts.date.formatを定義することで任意の形式を追加できる<br/><br/>

java.util.Date以外にも以下のようにjava.util.Dateを継承した型でも利用できる
　java.sql.Date
　java.sql.Timestamp
　java.sql.Time
　※java.util.Calendarは不可
<br/>
</dd>
  <dt>パラメータ</dt>
  <dd>

|名前|意味|既定値|
|--|--|--|
|min|最小値|null|
|max|最大値|null|
|minExpression|最小値を算出するための${...}形式のOGNL式|null|
|maxExpression|最大値を算出するための${...}形式のOGNL式|null|

※パラメータを設定しなかった項目については検証を行わない。<br/><br/>
</dd>
  <dt>使用例</dt>
  <dd>
<details><summary>XML</summary>

```xml
<!DOCTYPE validators PUBLIC "-//Apache Struts//XWork Validator 1.0.3//EN"
		"http://struts.apache.org/dtds/xwork-validator-1.0.3.dtd">
<validators>
     <!-- Plain Validator syntax -->
     <validator type="date">
         <param name="fieldName">birthday</param>
         <param name="min">01/01/1990</param>
         <param name="max">01/01/2000</param>
         <message>Birthday must be within ${min} and ${max}</message>
     </validator>
 
     <!-- Field Validator Syntax -->
     <field name="birthday">
         <field-validator type="date">
      	   <param name="min">01/01/1990</param>
             <param name="max">01/01/2000</param>
             <message>Birthday must be within ${min} and ${max}</message>
     	   </field>
     </field>
 
     <!-- Field Validator Syntax with expression -->
     <field name="birthday">
         <field-validator type="date">
             <param name="minExpression">${minValue}</param> <!-- will be evaluated as: Date getMinValue() -->
             <param name="maxExpression">${maxValue}</param> <!-- will be evaluated as: Date getMaxValue() -->
             <message>Age needs to be between ${min} and ${max}</message>
         </field-validator>
     </field>
</validators>
```
</details>
<details><summary>アノテーション</summary>

```java
    @DateRangeFieldValidator(message = "Default message", key = "i18n.key", shortCircuit = true, min = "2005/01/01", max = "2005/12/31")
    public Date getDate() {
        return this.date;
    }
```
</details>
</dd>
</dl>

## ExpressionValidator
<dl>
  <dt>機能</dt>
  <dd>OGNL式で検証を行う非フィールドレベルのValidator<br/><br/></dd>
  <dt>パラメータ</dt>
  <dd>

|名前|意味|既定値|
|--|--|--|
|expression|検証条件を記述したOGNL式。falseを返却した場合は検証エラーとなる。${...}や%{...}は記述せずそのままOGNL式を指定する。|null|

</dd>
  <dt>使用例</dt>
  <dd>
<details><summary>XML</summary>

```xml
<!DOCTYPE validators PUBLIC "-//Apache Struts//XWork Validator 1.0.3//EN"
		"http://struts.apache.org/dtds/xwork-validator-1.0.3.dtd">
<validators>
    <validator type="expression">
         <param name="expression"><![CDATA[username.length >= 5 && username.indexOf(@com.opensymphony.xwork2.Action@ERROR) == -1]]></param>
         <message>Username must be at least 5 characters and not contains "error"</message>
    </validator>
</validators>
```
</details>
<details><summary>アノテーション</summary>

```java
    @ExpressionValidator(message = "Default message", key = "i18n.key", shortCircuit = true, expression = "username.length > 5 && !username.startWith('ZZ')" )
    public String execute() throws Exception {
    }
```
</details>
</dd>
</dl>

## FieldExpressionValidator
<dl>
  <dt>機能</dt>
  <dd>OGNL式を使ってフィールドを検証する。<br/><br/></dd>
  <dt>パラメータ</dt>
  <dd>

|名前|意味|既定値|
|--|--|--|
|expression|検証条件を記述したOGNL式。falseを返却した場合は検証エラーとなる。${...}や%{...}は記述せずそのままOGNL式を指定する。|null|

</dd>
  <dt>使用例</dt>
  <dd>
<details><summary>XML</summary>

```xml
<!DOCTYPE validators PUBLIC "-//Apache Struts//XWork Validator 1.0.3//EN"
		"http://struts.apache.org/dtds/xwork-validator-1.0.3.dtd">
<validators>
    <!-- Plain Validator Syntax -->
    <validator type="fieldexpression">
       <param name="fieldName">myField</param>
       <param name="expression"><![CDATA[#myCreditLimit > #myGirfriendCreditLimit]]></param>
       <message>My credit limit should be MORE than my girlfriend</message>
    <validator>

    <!-- Field Validator Syntax -->
    <field name="myField">
        <field-validator type="fieldexpression">
            <param name="expression"><![CDATA[#myCreditLimit > #myGirfriendCreditLimit]]></param>
            <message>My credit limit should be MORE than my girlfriend</message>
        </field-validator>
    </field>
</validators>
```
</details>
<details><summary>アノテーション</summary>

```java
    @FieldExpressionValidator(message = "Username must not contain over one hyphen and not end with 'Z'", key = "i18n.key", shortCircuit = true, expression = "username.split('-').length < 3 && !username.endsWith('Z')")
    public String getUserName() {
        return this.username;
    }
```
</details>
</dd>
</dl>

## EmailValidator
<dl>
  <dt>機能</dt>
  <dd>Eメールアドレスとして妥当か以下の正規表現でチェックする。<br/>

`\\b^['_a-z0-9-\\+]+(\\.['_a-z0-9-\\+]+)*@[a-z0-9-]+(\\.[a-z0-9-]+)*\\.([a-z]{2,6})$\\b`<br/><br/></dd>
  <dt>パラメータ</dt>
  <dd>

|名前|意味|既定値|
|--|--|--|
|regex|マッチすべき正規表現|上記正規表現|
|regexExpression|マッチすべき正規表現を返却する${...}形式のOGNL式|null|
|caseSensitive|大文字小文字を区別するか|false|
|caseSensitiveExpression|大文字小文字を区別するかをbooleanで返却する${...}形式のOGNL式|null|
|trim|マッチングする前に前後の空白を除去するかどうか|true|
|trimExpression|trimするかどうかをbooleanで返却する${...}形式のOGNL式|null|

※いずれのパラメータもXMLのみ指定可能。<br/><br/>
</dd>
  <dt>使用例</dt>
  <dd>
<details><summary>XML</summary>

```xml
<!DOCTYPE validators PUBLIC "-//Apache Struts//XWork Validator 1.0.3//EN"
		"http://struts.apache.org/dtds/xwork-validator-1.0.3.dtd">
<validators>
    <!-- Plain Validator Syntax -->
    <validator type="email">
        <param name="fieldName">myEmail</param>
        <message>Must provide a valid email</message>
    </validator>

    <!-- Field Validator Syntax -->
    <field name="myEmail">
        <field-validator type="email">
            <message>Must provide a valid email</message>
        </field-validator>
    </field>

    <!-- Field Validator Syntax with expressions -->
    <!-- Only available when used with xml based configuration, if you want to have the same
         flexibility with annotations use @RegexFieldValidator instead -->
    <field name="myEmail">
        <field-validator type="email">
            <param name="regexExpression">${emailPattern}</param> <!-- will be evaluated as: String getEmailPattern() -->
            <param name="caseSensitiveExpression">${emailCaseSensitive}</param> <!-- will be evaluated as: boolean getEmailCaseSensitive() -->
            <param name="trimExpression">${trimEmail}</param> <!-- will be evaluated as: boolean getTrimEmail() -->
            <message>Must provide a valid email</message>
        </field-validator>
    </field>
</validators>
```
</details>
<details><summary>アノテーション</summary>

```java
    @EmailValidator(message = "Default message", key = "i18n.key", shortCircuit = true)
    public String getEmail() {
        return this.email;
    }
```
</details>
</dd>
</dl>

## CreditCardValidator
<dl>
  <dt>機能</dt>
  <dd>クレジットカード番号として妥当か以下の正規表現でチェックする。<br/>

|名前|正規表現|
|--|--|
|Visa|4[0-9]{12}(?:[0-9]{3})?|
|MasterCard|(?:5[1-5][0-9]{2}\|222[1-9]\|22[3-9][0-9]\|2[3-6][0-9]{2}\|27[01][0-9]\|2720)[0-9]{12}|
|American Express|3[47][0-9]{13}|
|Diners Club International|3(?:0[0-5]\|[68][0-9])[0-9]{11}|
|Discover Card|6(?:011\|5[0-9]{2})[0-9]{12}|
|JCB|(?:2131\|1800\|35\\\\d{3})\\\\d{11}|
  <dt>パラメータ</dt>
  <dd>

|名前|意味|既定値|
|--|--|--|
|regex|マッチすべき正規表現|上記正規表現|
|regexExpression|マッチすべき正規表現を返却する${...}形式のOGNL式|null|
|caseSensitive|大文字小文字を区別するか|false|
|caseSensitiveExpression|大文字小文字を区別するかをbooleanで返却する${...}形式のOGNL式|null|
|trim|マッチングする前に前後の空白を除去するかどうか|true|
|trimExpression|trimするかどうかをbooleanで返却する${...}形式のOGNL式|null|

※いずれのパラメータもXMLのみ指定可能。<br/><br/>
</dd>
  <dt>使用例</dt>
  <dd>
<details><summary>XML</summary>

```xml
<!DOCTYPE validators PUBLIC "-//Apache Struts//XWork Validator 1.0.3//EN"
		"http://struts.apache.org/dtds/xwork-validator-1.0.3.dtd">
<validators>
    <!-- Plain Validator Syntax -->
    <validator type="creditcard">
        <param name="fieldName">myCardNum</param>
        <message>Must provide a valid card number</message>
    </validator>

    <!-- Field Validator Syntax -->
    <field name="myCardNum">
        <field-validator type="creditcard">
            <message>Must provide a valid card number</message>
        </field-validator>
    </field>
</validators>
```
</details>
<details><summary>アノテーション</summary>

```java
    @CreditCardValidator(message = "Default message", key = "i18n.key", shortCircuit = true)
    public String getCardNum() {
        return this.cardNum;
    }
```
</details>
</dd>
</dl>

## URLValidator
<dl>
  <dt>機能</dt>
  <dd>URLとして妥当か以下の正規表現でチェックする。<br/>

`^(?:https?|ftp):\\/\\/(?:(?:[a-z0-9$_.+!*'(),;?&=\\-]|%[0-9a-f]{2})+(?::(?:[a-z0-9$_.+!*'(),;?&=\\-]|%[0-9a-f]{2})+)?@)?#?(?:(?:(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\\.)*[a-z][a-z0-9-]*[a-z0-9]|(?:(?:[1-9]?\\d|1\\d{2}|2[0-4]\\d|25[0-5])\\.){3}(?:[1-9]?\\d|1\\d{2}|2[0-4]\\d|25[0-5]))(?::\\d+)?)(?:(?:\\/(?:[a-z0-9$_.+!*'(),;:@&=\\-]|%[0-9a-f]{2})*)*(?:\\?(?:[a-z0-9$_.+!*'(),;:@&=\\-\\/:]|%[0-9a-f]{2})*)?)?(?:#(?:[a-z0-9$_.+!*'(),;:@&=\\-]|%[0-9a-f]{2})*)?$`

urlRegexとurlRegexExpressionを両方指定した場合、urlRegexExpressionが優先される。<br/><br/>

</dd>
  <dt>パラメータ</dt>
  <dd>

|名前|意味|既定値|
|--|--|--|
|urlRegex|URLを検証するための正規表現を指定する。|上記正規表現|
|urlRegexExpression|URLを検証するための正規表現を${...}形式のOGNL式で指定する。|null|

※urlRegex／urlRegexExpression以外はXMLのみ指定可能。<br/><br/>
</dd>
  <dt>使用例</dt>
  <dd>
<details><summary>XML</summary>

```xml
<!DOCTYPE validators PUBLIC "-//Apache Struts//XWork Validator 1.0.3//EN"
		"http://struts.apache.org/dtds/xwork-validator-1.0.3.dtd">
<validators>
    <!-- Plain Validator Syntax -->
    <validator type="url">
        <param name="fieldName">myHomePage</param>
        <message>Invalid homepage url</message>
    </validator>

    <!-- Field Validator Syntax -->
    <field name="myHomepage">
        <field-validator type="url">
            <message>Invalid homepage url</message>
        </field-validator>
    </field>
</validators>
```
</details>
<details><summary>アノテーション</summary>

```java
    @UrlValidator(message = "Default message", key = "i18n.key", shortCircuit = true)
    public String getURL() {
        return this.url;
    }
```
</details>
</dd>
</dl>

## VisitorFieldValidator
<dl>
  <dt>機能</dt>
  <dd>Action内に定義したオブジェクトプロパティの検証をオブジェクト自身のvalidationファイルで行えるようにする。これによりModelDrivenパターンを適用した開発ができ、Modelに対するvalidation定義を1か所で管理することができる。
VisitorFieldValidatorは単一のオブジェクトプロパティにも、オブジェクトのコレクションにも配列にも適用できる。
VisitorFieldValidatorへのエラーメッセージはオブジェクトの検証により追加されたメッセージの前に追加される。<br/><br/>
（例）以下のようにUserクラスのオブジェクトプロパティにcontext="myContext"のVisitorFieldValidatorを指定した場合

```java
    @VisitorFieldValidator(context = "myContext")
    public User getUser() {
        return this.user;
    }
```
検索されるvalidation.xmlファイルは以下となる。以下のうち存在するvalidation.xmlがすべて適用される。
<table>
<thead>
<th>#</th>
<th>パス</th>
<th>備考</th>
</thead>
<tbody>
<tr>
<td>1</td>
<td>java/lang/Object-validation.xml</td>
<td></td>
</tr>
<tr>
<td>2</td>
<td>java/lang/Object-myContext-validation.xml</td>
<td></td>
</tr>
<tr>
<td>3</td>
<td>Userの親クラスが実装しているインターフェイス-validation.xml
</td>
<td rowspan="4">Objectクラスに到達するまで繰り返す。親クラスのpackageのピリオドをスラッシュに置き換えたパスが検索される。<br/>（例）com.test.UserBaseの場合、com/test/UserBase-validation.xml</td>
</tr>
<tr>
<td>4</td>
<td>Userの親クラスが実装しているインターフェイス-myContext-validation.xml</td>
</tr>
<tr>
<td>5</td>
<td>Userの親クラス-validation.xml</td>
</tr>
<tr>
<td>6</td>
<td>Userの親クラス-myContext-validation.xml</td>
</tr>
<tr>
<td>7</td>
<td>Userが実装しているインターフェイス-validation.xml</td>
<td></td>
</tr>
<tr>
<td>8</td>
<td>Userが実装しているインターフェイス-myContext-validation.xml</td>
<td></td>
</tr>
<tr>
<td>9</td>
<td>User-validation.xml</td>
<td></td>
</tr>
<tr>
<td>10</td>
<td>User-myContext-validation.xml</td>
<td></td>
</tr>
</tbody>
</table>
※contextを指定しなかった場合は*-myContext-validation.xmlは検索されない。
<br/><br/>
</dd>
  <dt>パラメータ</dt>
  <dd>

|名前|意味|既定値|
|--|--|--|
|context|オブジェクトプロパティの検証に使用するコンテキスト|null|
|appendPrefix|エラー発生時にこのフィールドバリデータのフィールド名を検証対象のフィールドの名称に追加するかどうか。例としてフィールド"bean"が検証対象であり、その"name"フィールドでエラー発生が発生した場合、appendPrefixがtrueであれば"bean.name"の名前でエラーメッセージが検索され、falseであれば"name"で検索される。もしこのバリデータでModelDrivenを使ったModelを検証する場合、"model.name"の書き方でプロパティを参照するのであればappendPrefixにtrueを設定し、そうでなければfalseを設定する。|true|

</dd>
  <dt>使用例</dt>
  <dd>
<details><summary>XML</summary>

```xml
<!DOCTYPE validators PUBLIC "-//Apache Struts//XWork Validator 1.0.3//EN"
		"http://struts.apache.org/dtds/xwork-validator-1.0.3.dtd">
<validators>
    <!-- Plain Validator Syntax -->
    <validator type="visitor">
        <param name="fieldName">user</param>
        <param name="context">myContext</param>
        <param name="appendPrefix">true</param>
    </validator>
    <!-- Field Validator Syntax -->
    <field name="user">
        <field-validator type="visitor">
            <param name="context">myContext</param>
            <param name="appendPrefix">true</param>
        </field-validator>
    </field>
</validators>
```
</details>
<details><summary>アノテーション</summary>

```java
    @VisitorFieldValidator(message = "Default message", key = "i18n.key", shortCircuit = true, context = "myContext", appendPrefix = true)
    public User getUser() {
        return this.user;
    }
```
</details>
</dd>
</dl>

## ConversionErrorFieldValidator
<dl>
  <dt>機能</dt>
  <dd>型変換エラー（Integer型のフィールドにoneを指定するなど）が発生したかどうかチェックする。<br/>※ConversionErrorInterceptorが同等の処理を実施するのでその場合は使わなくてよい。<br/><br/></dd>
  <dt>パラメータ</dt>
  <dd>

|名前|意味|既定値|
|--|--|--|
|repopulateField|型変換エラー発生時に画面を再描画した際に元の値を復元するかどうか|false|

</dd>
  <dt>使用例</dt>
  <dd>
<details><summary>XML</summary>

```xml
<!DOCTYPE validators PUBLIC "-//Apache Struts//XWork Validator 1.0.3//EN"
		"http://struts.apache.org/dtds/xwork-validator-1.0.3.dtd">
<validators>
    <!-- Plain Validator Syntax -->
    <validator type="conversion">
        <param name="fieldName">myField</param>
        <message>Conversion Error Occurred</message>
    </validator>
    <!-- Field Validator Syntax -->
    <field name="myField">
        <field-validator type="conversion">
            <message>Conversion Error Occurred</message>
        </field-validator>
    </field>
</validators>
```
</details>
<details><summary>アノテーション</summary>

```java
    @ConversionErrorFieldValidator(message = "Default message", key = "i18n.key", shortCircuit = true)
    Integer getMyIntegerField() {
        return this.myIntegerField;
    }
```
</details>
</dd>
</dl>

## StringLengthFieldValidator
<dl>
  <dt>機能</dt>
  <dd>文字列フィールドの長さが指定した範囲内であるか検証する。<br/>
以下であればエラーなしと判定する。<br/>
(minLength or minLengthExpression) ≦フィールドの長さ ≦ (maxLength or maxLengthExpression)<br/><br/>
※minLength／minLengthExpressionとmaxLength／maxLengthExpressionのいずれも指定しない場合は何もしない。<br/>
※trim／minLength／maxLengthとtrimExpression／minLengthExpression／maxLengthExpressionの両方を指定した場合はtrimExpression／minLengthExpression／maxLengthExpressionが優先される。<br/>
※文字列フィールドがnullまたは空文字であれば検証を行わない。必要であれば合わせてRequiredStringValidatorを使用する。
 <br/><br/></dd>
  <dt>パラメータ</dt>
  <dd>

|名前|意味|既定値|
|--|--|--|
|trim|長さチェック前にtrimするかどうか|true|
|trimExpression|長さチェック前にtrimするかどうかをbooleanで返却する${...}形式のOGNL式|null|
|minLength|長さの最小値。デフォルトは無視される|-1|
|minLengthExpression|長さの最小値をintで返却する${...}形式のOGNL式|null|
|maxLength|長さの最大値。デフォルトは無視される|-1|
|maxLengthExpression|長さの最大値をintで返却する${...}形式のOGNL式|null|

</dd>
  <dt>使用例</dt>
  <dd>
<details><summary>XML</summary>

```xml
<!DOCTYPE validators PUBLIC "-//Apache Struts//XWork Validator 1.0.3//EN"
		"http://struts.apache.org/dtds/xwork-validator-1.0.3.dtd">
<validators>
    <!-- Plain Validator Syntax -->
    <validator type="stringlength">
        <param name="fieldName">myPurchaseCode</param>
        <param name="minLength">10</param>
        <param name="maxLength">10</param>
        <param name="trim">true</param>
        <message>Your purchase code needs to be 10 characters long</message>
    </validator>

    <!-- Field Validator Syntax -->
    <field name="myPurchaseCode">
        <field-validator type="stringlength">
            <param name="minLength">10</param>
            <param name="maxLength">10</param>
            <param name="trim">true</param>
            <message>Your purchase code needs to be 10 characters long</message>
        </field-validator>
    </field>

    <!-- Field Validator Syntax with expression -->
    <field name="myPurchaseCode">
        <field-validator type="stringlength">
            <param name="minLengthExpression">${minLengthValue}</param> <!-- will be evaluated as: Integer getMinLengthValue() -->
            <param name="maxLengthExpression">${maxLengthValue}</param> <!-- will be evaluated as: Integer getMaxLengthValue() -->
            <param name="trimExpression">${trimValue}</param> <!-- will be evaluated as: boolean getTrimValue() -->
            <message>Your purchase code needs to be 10 characters long</message>
        </field-validator>
    </field>
</validators>
```
</details>
<details><summary>アノテーション</summary>

```java
    @StringLengthFieldValidator(message = "Default message", key = "i18n.key", shortCircuit = true, trim = true, minLength = "5",  maxLength = "12")
    String getMyPurchaseCode() {
        return this.myPurchaseCode;
    }
```
</details>
</dd>
</dl>

## RegexFieldValidator
<dl>
  <dt>機能</dt>
  <dd>文字列フィールドが指定した正規表現のパターンに一致するか検証する。<br/>regexp／caseSensitive／trimとregexExpression／caseSensitiveExpression／trimExpressionの両方を指定した場合はregexp／caseSensitiveExpression／trimExpressionが優先される。<br/><br/></dd>
  <dt>パラメータ</dt>
  <dd>

|名前|意味|既定値|
|--|--|--|
|regexp|正規表現のパターンを指定する。|null|
|caseSensitive|正規表現の判定で大文字と小文字を識別するかどうか。trueの場合、大文字小文字を区別しない。|true|
|trim|正規表現の判定前にtrimするかどうか。|true|
|regexExpression|正規表現のパターンを返却する${...}形式のOGNL式|null|
|caseSensitiveExpression|正規表現の判定で大文字と小文字を識別するかどうかをbooleanで返却する${...}形式のOGNL式|""|
|trimExpression|正規表現の判定前にtrimするかどうかをbooleanで返却する${...}形式のOGNL式|""|

</dd>
  <dt>使用例</dt>
  <dd>
<details><summary>XML</summary>

```xml
<!DOCTYPE validators PUBLIC "-//Apache Struts//XWork Validator 1.0.3//EN"
		"http://struts.apache.org/dtds/xwork-validator-1.0.3.dtd">
<validators>
    <!-- Plain Validator Syntax -->
    <validator type="regex">
        <param name="fieldName">myStrangePostcode</param>
        <param name="regex"><![CDATA[([aAbBcCdD][123][eEfFgG][456])]]></param>
    </validator>

    <!-- Field Validator Syntax -->
    <field name="myStrangePostcode">
        <field-validator type="regex">
            <param name="regex"><![CDATA[([aAbBcCdD][123][eEfFgG][456])]]></param>
        </field-validator>
    </field>

    <!-- Field Validator Syntax with expressions -->
    <field name="myStrangePostcode">
        <field-validator type="regex">
            <param name="regexExpression">${regexValue}</param> <!-- will be evaluated as: String getRegexValue() -->
            <param name="caseSensitiveExpression">${caseSensitiveValue}</param> <!-- will be evaluated as: boolean getCaseSensitiveValue() -->
            <param name="trimExpression">${trimValue}</param> <!-- will be evaluated as: boolean getTrimValue() -->
        </field-validator>
    </field>
</validators>
```
</details>
<details><summary>アノテーション</summary>

```java
    @RegexFieldValidator( key = "regex.field", regex = "([aAbBcCdD][123][eEfFgG][456])")
    String getMyStrangePostcode() {
        return this.myStrangePostcode;
    }
```
</details>
</dd>
</dl>

## ConditionalVisitorFieldValidator
<dl>
  <dt>機能</dt>
  <dd>条件に一致した場合だけVisitorFieldValidatorに検証を行わせる。詳細はVisitorFieldValidator参照
<br/><br/></dd>
  <dt>パラメータ</dt>
  <dd>

|名前|意味|既定値|
|--|--|--|
|expression|検証を行うかどうかをbooleanで返却するOGNL式。trueの場合、VisitorFieldValidatorで検証を行う。|null|
|context|VisitorFieldValidator参照|null|
|appendPrefix|VisitorFieldValidator参照|true|

</dd>
  <dt>使用例</dt>
  <dd>
<details><summary>XML</summary>

```xml
<!DOCTYPE validators PUBLIC "-//Apache Struts//XWork Validator 1.0.3//EN"
		"http://struts.apache.org/dtds/xwork-validator-1.0.3.dtd">
<validators>
    <field name="colleaguePosition">
        <field-validator type="conditionalvisitor">
            <param name="expression">reason == 'colleague' and colleaguePositionID == 'OTHER'</param>
            <message>You must select reason Colleague and position Other</message>
        </field-validator>
    </field>
</validators>
```
</details>
<details><summary>アノテーション</summary>

```java
    @ConditionalVisitorFieldValidator(expression="user.id > 100",  message = "Default message", key = "i18n.key", shortCircuit = true, context = "myContext", appendPrefix = true)
    User getUser() {
        return this.user;
    }
```
</details>
</dd>
</dl>


# short-circuitについて
以下のようなshort-circuit="true"を指定したValidatorを定義した場合、エラーが発生した箇所によって実施される検証は表のようになる。
```xml
<!DOCTYPE validators PUBLIC "-//Apache Struts//XWork Validator 1.0.3//EN"
		"http://struts.apache.org/dtds/xwork-validator-1.0.3.dtd">
<validators>
     <!-- 1.アクションレベルのvalidator-->
     <validator type="expression" short-circuit="true">
         <param name="expression"><![CDATA[username.indexOf('error') < 0]]></param>
         <message>Username must not contains "error"</message>
     </validator>
     <!-- 2.フィールドvalidator -->
     <validator type="stringlength" short-circuit="true">
         <param name="fieldName">myUrl</param>
         <param name="minLength">10</param>
         <param name="maxLength">100</param>
         <message>Url length needs to be between ${minLength} and ${maxLength}</message>
     </validator>
     <!-- 3.フィールドvalidator -->
     <field name="myUrl">
         <field-validator type="url" short-circuit="true">
             <message>Url invalid</message>
         </field-validator>
     </field>
     <!-- 4.フィールドvalidator -->
     <validator type="int" short-circuit="true">
         <param name="fieldName">age</param>
         <param name="min">15</param>
         <param name="max">65</param>
         <message>Age needs to be between ${min} and ${max}</message>
     </validator>
</validators>
```
|エラー箇所|実施される検証|説明|
|--|--|--|
|1.アクションレベルのvalidator|1のみ|アクションレベルのvalidatorでエラーが発生した場合は、以降の検証をすべて行わない。|
|2.フィールドvalidator|1、2、4|フィールドvalidatorでエラーが発生した場合は、同じフィールドの以降の検証については行わない。|
|3.フィールドvalidator|1、2、3、4|フィールドvalidatorの最後でエラーが発生した場合はshort-circuitは行われない。|
|4.フィールドvalidator|1、2、3、4|3と同様|


# Validationの無効化
初期表示や単純に別画面に移動する機能ではValidationを無効にしたいことがある。
その場合は@org.apache.struts2.interceptor.validation.SkipValidationアノテーションをアクションメソッドに付与する。
```java
    @SkipValidation
    public String execute() {
        // 初期処理など
        return "success";
    }
```

# アクションメソッド毎のValidation定義
[Validationの定義方法](https://qiita.com/tm777/items/0dd91fd0ac82b2530f0d#validation%E3%81%AE%E5%AE%9A%E7%BE%A9%E6%96%B9%E6%B3%95 "Validationの定義方法")に記載したとおりvalidation.xmlはファイル名にアクション名を含んだものを定義できるので、アクション毎のValidation定義が可能だが、アノテーションで定義する方法では利用できない。以下に説明する方法を利用すればアノテーションで定義する場合でもアクション毎のValidation定義が可能になる。
たとえば同一アクションクラスにhelloとgreetの2つのアクションがあり。helloではusernameの必須チェックを行うが、greetでは桁数チェックを行う場合は以下の設定を行う。
- AnnotationValidationInterceptorのvalidateAnnotatedMethodOnlyプロパティにtrueを設定する。
<dl><dd><details>

```xml:struts.xml ※action内で設定した場合
    <action name="hello" class="org.demo.actions.HelloAction">
        <interceptor-ref name="defaultStack">
            <!-- validateAnnotatedMethodOnlyプロパティの設定 -->
            <param name="validation.validateAnnotatedMethodOnly">true</param>
        </interceptor-ref>
        <result name="success">/WEB-INF/content/hello.jsp</result>
        <result name="input">/WEB-INF/content/hello.jsp</result>
    </action>
    <action name="greet" class="org.demo.actions.HelloAction" method="greet">
        <interceptor-ref name="defaultStack">
            <!-- validateAnnotatedMethodOnlyプロパティの設定 -->
            <param name="validation.validateAnnotatedMethodOnly">true</param>
        </interceptor-ref>
        <result name="success">/WEB-INF/content/greet.jsp</result>
        <result name="input">/WEB-INF/content/greet.jsp</result>
    </action>
```
</details></dd></dl>

- Validationを定義する
<dd><dl><details><summary>XML</summary>
XMLの場合は以下のようにmethodNameパラメータに対象のメソッド名を指定する。

```xml
<!DOCTYPE validators PUBLIC "-//Apache Struts//XWork Validator 1.0.3//EN"
		"http://struts.apache.org/dtds/xwork-validator-1.0.3.dtd">
<validators>
    <!-- helloアクションのみ実施する検証 -->
    <validator type="requiredstring">
        <param name="fieldName">username</param>
        <param name="trim">true</param>
        <!-- executeメソッド（※actionタグでmethod属性が省略された場合のデフォルト値）のみ実施 -->
        <param name="methodName">execute</param>
        <message>username is required</message>
    </validator>
    <!-- greetアクションのみ実施する検証 -->
    <validator type="stringlength">
        <param name="fieldName">username</param>
        <param name="maxLength">20</param>
        <!-- greetメソッドのみ実施 -->
        <param name="methodName">greet</param>
        <message>username needs to be less than 20 characters</message>
    </validator>
</validators>
```
※validateAnnotatedMethodOnlyにtrueを設定した場合、methodNameを指定していない検証は実施されない。

</details>
<details><summary>アノテーション</summary>
アクションメソッドに対してアノテーションを設定する。検証対象フィールドをfieldName属性で指定する。

```java:HelloAction.java
public class HelloAction extends ActionSupport {
    private String username;
    public String getUsername() { return this.username; }
    public void setUsername(String username) { this.username = username; }

    @RequiredStringValidator(fieldName = "username", message = "username is required", trim = true)
    public String execute() {
        return SUCCESS;
    }

    @StringLengthFieldValidator(fieldName = "username", message = "username needs to be less than 20 characters", maxLength = "20")
    public String greet() {
        return SUCCESS;
    }
}
```

※validateAnnotatedMethodOnlyにtrueを設定した場合、getter等に対してアノテーションを設定したValidationは実施されない。
</details>
</dd>
</dl>

- 動作イメージ
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/132879/0107334a-1956-2cfd-73e3-3c74cc1ffc00.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/132879/6fd232ef-b76c-f11a-2a6d-82b707c99a6d.png)


# 複数アノテーションの一括指定
1つのフィールドに対して複数のアノテーションを付与することもできるが、@Validationsアノテーションを使用すれば一括して指定することもできる。メソッドに対してアノテーションを付与する場合に便利かもしれない。

```java
    @Validations(
        requiredFields =
            {@RequiredFieldValidator(type = ValidatorType.SIMPLE, fieldName = "customfield", message = "You must enter a value for field.")},
        requiredStrings =
            {@RequiredStringValidator(type = ValidatorType.SIMPLE, fieldName = "stringisrequired", message = "You must enter a value for string.")},
        emails =
            { @EmailValidator(type = ValidatorType.SIMPLE, fieldName = "emailaddress", message = "You must enter a value for email.")},
        urls =
            { @UrlValidator(type = ValidatorType.SIMPLE, fieldName = "hreflocation", message = "You must enter a value for email.")},
        stringLengthFields =
                {@StringLengthFieldValidator(type = ValidatorType.SIMPLE, trim = true, minLength="10" , maxLength = "12", fieldName = "needstringlength", message = "You must enter a stringlength.")},
        intRangeFields =
                { @IntRangeFieldValidator(type = ValidatorType.SIMPLE, fieldName = "intfield", min = "6", max = "10", message = "bar must be between ${min} and ${max}, current value is ${bar}.")},
        longRangeFields =
                { @LongRangeFieldValidator(type = ValidatorType.SIMPLE, fieldName = "intfield", min = "6", max = "10", message = "bar must be between ${min} and ${max}, current value is ${bar}.")},
        shortRangeFields =
                { @ShortRangeFieldValidator(type = ValidatorType.SIMPLE, fieldName = "shortfield", min = "1", max = "128", message = "bar must be between ${min} and ${max}, current value is ${bar}.")},
        dateRangeFields =
                {@DateRangeFieldValidator(type = ValidatorType.SIMPLE, fieldName = "datefield", min = "-1", max = "99", message = "bar must be between ${min} and ${max}, current value is ${bar}.")},
        expressions = {
            @ExpressionValidator(expression = "foo > 1", message = "Foo must be greater than Bar 1. Foo = ${foo}, Bar = ${bar}."),
            @ExpressionValidator(expression = "foo > 2", message = "Foo must be greater than Bar 2. Foo = ${foo}, Bar = ${bar}."),
            @ExpressionValidator(expression = "foo > 3", message = "Foo must be greater than Bar 3. Foo = ${foo}, Bar = ${bar}."),
            @ExpressionValidator(expression = "foo > 4", message = "Foo must be greater than Bar 4. Foo = ${foo}, Bar = ${bar}."),
            @ExpressionValidator(expression = "foo > 5", message = "Foo must be greater than Bar 5. Foo = ${foo}, Bar = ${bar}.")
    }
    )
    public String execute() throws Exception {
        return SUCCESS;
    }
```

# XMLにおける&lt;message&gt;の書き方
validation.xmlファイルの&lt;message&gt;要素の指定方法はi18n（国際化対応）をする／しないで異なっており、メッセージに画面の入力項目などを含めることができる。Plain Validatorシンタックス、Field Validatorシンタックスで書き方は同じである。
### i18n（国際化対応）なし
以下のように&lt;message&gt;要素にkey属性を付けずに記述する。messageボディに\\${...}あるいは%{...}の形式でOGNL式を指定できる。$と%は同じ意味だが、混在させると%{...}のほうが変換されないバグがあるようだ。

```xml
<!DOCTYPE validators PUBLIC "-//Apache Struts//XWork Validator 1.0.3//EN"
		"http://struts.apache.org/dtds/xwork-validator-1.0.3.dtd">
<validators>
     <validator type="int">
         <param name="fieldName">age</param>
         <param name="min">20</param>
         <param name="max">50</param>
         <message>Age needs to be between ${min} and ${max}</message>
     </validator>
</validators>
```
OGNL式には次のような値が指定できる。
<ul>
<li>共通のフィールド　※ExpressionValidatorを除く

|OGNL式|値|
|--|--|
|${fieldName}|フィールド名。上の例の場合age|
|${currentValue}|フィールドの現在の値。10など|

</li>
<li>使用しているValidatorのパラメータ（上の例の場合、min、maxなど）</li>
<li>Actionクラスのフィールド。例えば画面の入力項目としてuserIdとpasswordがある場合で、userIdとpasswordが同じときにエラーメッセージを出力する場合、<br/>

```xml
<message>パスワードにユーザーIDと同じ値（${userId}）は指定できません。</message>
```
</li>
<li>Actionクラスのメソッド呼び出し。例えばActionクラスのベースクラスActionSupportのgetTextメソッドを呼び出す場合

```xml
<message>${getText(fieldName)}: must be from ${min} to ${max}</message>
```
</li>
</ul>

### i18n（国際化対応）あり
以下のように&lt;message&gt;要素にkey属性を付けて記述する。keyには対応するxxxAction.propertiesのキーを指定する。
メッセージに埋め込むパラメータを&lt;param name="1"&gt;の形式で1から順に指定することができ、messageの0から始まるプレースホルダー（{0}、{1}など）に埋め込まれる。&lt;param name="1"&gt;のボディはOGNL式であり、リテラルを記述したい場合はシングルクォーテーションで明示的に括る必要がある。

```xml
<!DOCTYPE validators PUBLIC "-//Apache Struts//XWork Validator 1.0.3//EN"
		"http://struts.apache.org/dtds/xwork-validator-1.0.3.dtd">
<validators>
     <validator type="int">
         <param name="fieldName">age</param>
         <param name="min">20</param>
         <param name="max">50</param>
         <message key="age.range.error">
              <param name="1">fieldName</param>
              <param name="2">'fieldName'</param>
              <param name="defaultMessage">{0}{1}</param>
         </message>
     </validator>
</validators>
```

```xxxAction.properties
age.range.error={0}: must be from ${min} to ${max}
```
```xxxAction_jp.properties
age.range.error={0}は${min}から${max}の範囲で指定してください。
```
上の例はブラウザの設定が日本語の場合「ageは20から50の範囲で指定してください。」というエラーメッセージが表示される。
&lt;message&gt;要素のkey属性に指定したキーがxxxAction.propertiesに存在しない場合、&lt;param name="defaultMessage"&gt;に指定したmessageが使用される。