実案件では、Bean ValidationとHibernateValidatorで用意されているバリデーションだけでは不十分なことが多いです。そこで、独自にバリデーション用のアノテーションを作成します。
Contents
独自のバリデーション用アノテーションを作成する2つの方法
- 既存のアノテーションを合成して作成する
- チェックロジックを独自に実装する(完全に独自アノテーション)
多くの場合は、正規表現でアノテーションを作成するため、1の方法を推奨します。1の方が作成するクラスが1つ減るためシンプルです。
【推奨】既存のアノテーションを合成して作成する
Bean Validationの仕組みを利用して、アノテーションを実装することができます。下記は、全角ひらがなのチェック用アノテーションです。
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.FIELD})
@Documented
@Constraint(validatedBy = {})
@ReportAsSingleViolation
@Pattern(regexp = "[\u3041-\u3096]*")
public @interface Hiragana {
String message() default "ひらがなで入力してください";
Class<?>[] groups() default { };
Class<? extends Payload>[] payload() default { };
@Target({ METHOD, FIELD, ANNOTATION_TYPE, CONSTRUCTOR, PARAMETER })
@Retention(RUNTIME)
@Documented
public @interface List {
Hiragana[] value();
}
}
6行目の@Patternでjavax.validation.constraintsを合成しています。正規表現だけひらがなに変えているだけです。これだけで、下記のようにDTOで使用できます。
@Data
public class Mem01PostRequest {
@NotBlank
private String nameSei;
@Hiragana
private String kanaSei;
}
No | アノテーション | 意味・値 |
1 | @Retention | アノテーションで付加された情報がどの段階まで保持されるかを定義 RetentionPolicy.RUNTIME/CLASS/SOURCE |
2 | @Target | アノテーションを付与できる対象を指定 ElementType. TYPE/METHOD/FIELD/PARAMETER |
3 | @Documented | |
4 | @Constraint | Bean Validationの仕組みを利用することを宣言する。 #initialize と #isValid を定義する。 |
5 | @ReportAsSingleViolation | String message() default で指定したメッセージを使用することを表す。省略すると、親アノテーションのメッセージになる。 |
6 | @Pattern | 正規表現でチェックすることを表すアノテーション。 |
メッセージのカスタマイズ方法
固定メッセージをプロパティファイルから取得する
Bean Validationの仕組みを利用した場合、validationMessages.propertiesにメッセージを定義する決まりです。下記の要領です。
// 省略
public @interface Hiragana {
String message() default "{validation.Hiragana.message}";
Class<?>[] groups() default { };
Class<? extends Payload>[] payload() default { };
// 省略
}
波カッコの中にメッセージのキーを指定します。
validation.Hiragana.message=ひらがなで入力してください。
プロパティファイルにキー=メッセージの形式で記述します。
固定メッセージに項目名を埋め込む
現場ではさらに「○○は○○で入力してください」のように、項目名も求められることが多いです。項目名を表示しないと、ユーザは「どの項目のこと?」と迷ってしまい不親切です。
// 省略
public @interface Hiragana {
String fieldName();
String message() default "{validation.Hiragana.message}";
// 省略
}
バリデーションのアノテーションにfieldNameを追加します。表示する名前を保持できるようにします。
※filedNameという名前でなくても良いです。name/valueなど何でも良いです。
@Data
public class Mem01PostRequest {
@NotBlank
private String nameSei;
@Hiragana(fieldName = "かな性")
private String kanaSei;
}
アノテーションの引数に、fieldNameを追加して表示する名前を与えます。
validation.Hiragana.message={fieldName}はひらがなで入力してください。
メッセージにはこのように埋め込むことができます。
チェックロジックを独自に実装する
作成するのは2つです。
- アノテーションを定義するインターフェース
- バリデーションロジックを定義するクラス
アノテーションを定義するインターフェース
アノテーション自体を@interfaceを用いて定義します。
バリデーションロジックを定義するクラス
ConstraintValidator<アノテーションクラス, バリデーション対象の型>を指定する。