Spring Bootの独自アノテーションで、特定のフィールドに対するチェック処理も実装することができる。今回は、特定のフィールドの全角チェックを行うアノテーションを作成してみたので、共有する。
前提条件
下記記事の実装が完了していること。
サンプルプログラムの作成
作成したサンプルプログラムの構成は以下の通り。

なお、上図の赤枠のうち、「CheckZenkaku.java」「CheckZenkakuValidator.java」が、前提条件のプログラムから新規追加したプログラムで、他は変更したプログラムとなる。
まず、「CheckZenkaku」アノテーションの内容は以下の通りで、@CheckZenkakuアノテーションはフィールド指定(ElementType.FIELD)とし、表示するデフォルトエラーメッセージの指定をしている。
package com.example.demo.check;
import javax.validation.Constraint;
import javax.validation.Payload;
import java.lang.annotation.Target;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Documented;
//アノテーションの付与対象をフィールド(ElementType.FIELD)にする
//RetentionPolicyはclassファイルに記録され実行時に参照できるモード(Runtime)とする
//JavaDoc指定対象(@Documented)とする
//バリデーションの実装クラスはCheckDateValidatorクラスとする
@Target({ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Constraint(validatedBy={CheckZenkakuValidator.class})
public @interface CheckZenkaku {
//表示するエラーメッセージ(アノテーション属性で指定)
String message() default "{validation.zenkaku}";
//特定のバリデーショングループがカスタマイズできるような設定
Class<?>[] groups() default {};
//チェック対象のオブジェクトになんらかのメタ情報を与えるためだけの宣言
Class<? extends Payload>[] payload() default {};
}
なお、表示するエラーメッセージ(validation.zenkaku)は、以下のmessagesプロパティで指定している。
#メッセージ
validation.date-empty={0}を入力してください。
validation.date-invalidate=生年月日が存在しない日付になっています。
validation.date-future=生年月日が未来の日付になっています。
validation.empty-msg=
javax.validation.constraints.NotEmpty.message={0}を入力してください。
validation.sex-invalidate=性別に不正な値が入っています。
validation.date-invalidate-from=生年月日(From)の日付が不正です。
validation.date-invalidate-to=生年月日(To)の日付が不正です。
validation.date-invalidate-from-to=生年月日(From)が生年月日(To)より大きくなっています。
validation.zenkaku={0}は全角で入力してください。
#フィールド名
name=名前
sex=性別
checked=確認チェック
birthDayRequired=生年月日
また、「CheckZenkaku」アノテーションでのチェック処理を実装しているプログラムは以下の通りで、アノテーションの指定値が、空白値か全て全角文字の場合はtrueを返すようにしている。
package com.example.demo.check;
import org.springframework.util.StringUtils;
import javax.validation.ConstraintValidator;
import javax.validation.ConstraintValidatorContext;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class CheckZenkakuValidator
implements ConstraintValidator<CheckZenkaku, String> {
/**
* 全角チェックを行うための正規表現
* (コンパイルに時間がかかるためあらかじめ定数化しておく)
*/
private static Pattern pattern = Pattern.compile("^[^!-~。-゚]*$");
@Override
public void initialize(CheckZenkaku annotation) {
//初期化処理は不要
}
@Override
public boolean isValid(String value, ConstraintValidatorContext context) {
//valueには、アノテーションを付与したフィールドの項目値が設定される
//valueが空白値か、全て全角文字の場合はtrueを返すチェック処理を行う
if(StringUtils.isEmpty(value)){
return true;
}
Matcher matcher = pattern.matcher(value);
return matcher.find();
}
}
なお、上記プログラム内に特に記載が無いが、エラーの場合は、アノテーションの指定項目が赤反転するようになっている。
さらに、「DemoForm.java」の内容は以下の通りで、「名前」に「@CheckZenkaku」アノテーションが付与されている。
package com.example.demo;
import com.example.demo.check.CheckDate;
import com.example.demo.check.CheckZenkaku;
import com.example.demo.check.FutureDate;
import lombok.Data;
import org.thymeleaf.util.StringUtils;
import javax.validation.constraints.AssertTrue;
import javax.validation.constraints.NotEmpty;
import java.io.Serializable;
import java.util.LinkedHashMap;
import java.util.Map;
//日付チェック・未来日チェックを独自アノテーションで実施
@Data
@CheckDate(dtYear = "birthYear", dtMonth = "birthMonth", dtDay = "birthDay"
, message = "{validation.date-invalidate}")
@FutureDate(dtYear = "birthYear", dtMonth = "birthMonth", dtDay = "birthDay"
, message = "{validation.date-future}")
public class DemoForm implements Serializable {
/** ID */
private String id;
/** 名前 */
@NotEmpty
@CheckZenkaku
private String name;
/** 生年月日_年 */
private String birthYear;
/** 生年月日_月 */
private String birthMonth;
/** 生年月日_日 */
private String birthDay;
/** 性別 */
@NotEmpty
private String sex;
/** メモ */
private String memo;
/** 確認チェック */
@NotEmpty
private String checked;
/** 性別(文字列) */
private String sex_value;
/** 生年月日_月のMapオブジェクト */
public Map<String,String> getMonthItems(){
Map<String, String> monthMap = new LinkedHashMap<String, String>();
for(int i = 1; i <= 12; i++){
monthMap.put(String.valueOf(i), String.valueOf(i));
}
return monthMap;
}
/** 生年月日_日のMapオブジェクト */
public Map<String,String> getDayItems(){
Map<String, String> dayMap = new LinkedHashMap<String, String>();
for(int i = 1; i <= 31; i++){
dayMap.put(String.valueOf(i), String.valueOf(i));
}
return dayMap;
}
/** 性別のMapオブジェクト */
public Map<String,String> getSexItems(){
Map<String, String> sexMap = new LinkedHashMap<String, String>();
sexMap.put("1", "男");
sexMap.put("2", "女");
return sexMap;
}
/**
* 生年月日の年・月・日が入力されているかをチェックする
* @return チェック結果
*/
@AssertTrue(message = "{validation.date-empty}")
public boolean isBirthDayRequired(){
if(StringUtils.isEmpty(birthYear)
&& StringUtils.isEmpty(birthMonth)
&& StringUtils.isEmpty(birthDay)){
return false;
}
return true;
}
/**
* 性別が不正な値でないかチェックする
* @return チェック結果
*/
@AssertTrue(message = "{validation.sex-invalidate}")
public boolean isSexInvalid(){
return StringUtils.isEmpty(sex) || getSexItems().keySet().contains(sex);
}
}その他のソースコード内容は、以下のサイトを参照のこと。
https://github.com/purin-it/java/tree/master/spring-boot-web-check-zenkaku/demo
サンプルプログラムの実行結果
入力画面で、名前に全角文字以外が含まれている場合は、以下のように、エラーメッセージを表示し、エラー項目を赤反転するようになっている。

また、名前を全角文字のみにして「確認」ボタンを押下すると、エラーにならず、次の確認画面に遷移する。


要点まとめ
- Spring Bootの独自アノテーションで、特定のフィールドに対するチェック処理も実装することができる。その際、@Targetアノテーションでは「ElementType.FIELD」を指定する。





