読者です 読者をやめる 読者になる 読者になる

アラカン"BOKU"のITな日常

あれこれ興味をもって考えたことを書いてます

入力チェック:アノテーション定義を自分で作る。(再利用版)STS 3.8.3(Spring Boot 1.5.1)+thymeleaf 

Spring Boot +thymeleafの入力チェックで、@Patternを使えば、大抵のことができます。

arakan-pgm-ai.hatenablog.com

 

その通りなのですが、前にも書いたとおり、このやり方にはちょっと欠点があります。

 

超わかりづらいことです。こんな感じの記述が、1箇所ならともかく、たくさんあると、ちょっと管理しづらいですね。

@Pattern(regexp = "^(https?|ftp)(:\\/\\/[-_.!~*\\'()a-zA-Z0-9;\\/?:\\@&=+\\$,%#]+)$") 

 

やっぱり、@UrlValid とか @EmailValid とかのわかりやすい名前のアノテーションを使ってやりたいわけです。 

 

ということで、今回は@Patternで指定する正規表現を使って、わかりやすい名前の独自入力チェック用アノテーションを作ってみます。

 

独自入力チェックアノテーションは、形式が決まってます。今回、Eメールの正規表現パターンを使った独自アノテーション定義を作り、それを例にして形式を整理してみます。

 

今回の例にするアノテーション定義です。

import java.lang.annotation.*;
import javax.validation.*;
import javax.validation.constraints.Pattern;

import static java.lang.annotation.ElementType.*;
import static java.lang.annotation.RetentionPolicy.*;

@Documented
@Constraint(validatedBy={})
@Target({FIELD,ANNOTATION_TYPE})
@Retention(RUNTIME)
@ReportAsSingleViolation
@Pattern(regexp="^([\\w])+([\\w\\._-])*\\@([\\w])+([\\w\\._-])*\\.([a-zA-Z])+$")
public @interface EmailValid {
      String message() default "{0}はメールアドレスとして許可された形式ではありません。";
      Class<?> groups() default {};
      Class<? extends Payload>
payload() default {};

      @Target({FIELD,ANNOTATION_TYPE})
      @Retention(RUNTIME)
      @Documented
      public @interface List {
             EmailValid value();
      }
}

 

いろいろ、決め事があるので、整理していきます。

 

まず、独自アノテーション定義は、public @interface で定義します。今回の例では、public @interface EmailValidなので、@EmailValidというアノテーションとして使います。

 

次に、このアノテーション定義をバリデーションで使うための、決め事にそってアノテーションを付与していきます。

  • @Documented を固定で付与します。
  • @Retention(RUNTIME)  も固定で付与します。

次に、エラーメッセージをの取得先を指定します。以下のアノテーションを付与すると、ここで「message default」で定義したエラーメッセージを使います。付与しなかった場合は、もとのメッセージ(例えば@Patternを使ったときは、Patternで定義されているメッセージを使います。

@ReportAsSingleViolation

 

次に、@Patternの様な標準アノテーションを再利用・集約するか、独自にチェックを実装するかを@Constraintで指定します。

  • @Constraint(validatedBy={})は。今回の例のように標準アノテーションを再利用・集約する場合の書き方です。独自実装でロジックを組むときは、その実装クラスを{}の中に指定します。

次にアノテーションを設定する場所を@Targetで指定します。

  • @Target({FIELD,ANNOTATION_TYPE}) 

 

上記の@Targetの{}内で指定可能な場所は以下があります。

  • TYPE: インターフェース、クラス、列挙型などに付加する。
  • CONSTRUCTOR: コンストラクタに付加する。
  • FIELD: フィールド・列挙型の要素に付加する。
  • METHOD: クラス等のメソッド、アノテーション定義のメソッド宣言に付加する。
  • PARAMETER :パラメータ、メソッド宣言の引数の箇所に付加する。
  • LOCAL_VARIABLE: ローカル変数に付加する。
  • ANNOTATION_TYPE アノテーション定義に付加する。

 

今回の例では、Formクラスの変数のみにきかせるだけなので、FIELDとANNOTATION_TYPEにしているわけです。

 

あと、アノテーション定義の中でメソッドを定義するのですが、ここの部分はほぼ固定的に書くものが決まっています。 

 

まず、message()は、このアノテーションで表示するエラーメッセージを定義します。

String message() default "{0}はメールアドレスとして許可された形式ではありません。";

 

次の2つは、必ず定義しておかないといけませんが、特に変更する必要はありません。

Class<?> groups() default {};
Class<? extends Payload> payload() default {};

 

最後に、自分自身(例の場合だと EmailValidアノテーション定義)の配列を返すように書きます。

public @interface List {
        EmailValid value();
}

 

これで決まった形式は終わりです。今回は、独自ロジックを実装せず、標準アノテーションを再利用して使いやすくするだけなので、正規表現でメールフォーマットを検査する「@Pattern(regexp="^([\\w])+([\\w\\._-])*\\@([\\w])+([\\w\\._-])*\\.([a-zA-Z])+$")」を、そのまま書いています。

 

こうやって作った独自アノテーションを早速利用してみます。@Patternで書いていた部分を@EmailValidで置き換えます。

@EmailValid
private String chktest;

public String getChktest() {
      return chktest;
}

public void setChktest(String chktest) {
       this.chktest = chktest;
}

 

これで、Eメールアドレスとして駄目な@2つのパターンを入力してみます。

f:id:arakan_no_boku:20170326001708j:plain

 

いけてるみたいです。

 


 STS  3.8.3(Spring Boot 1.5.1)+thymeleaf 関連記事

 

入力画面に関連する記事

画像をSUBMITボタン代わりに使う

ラジオボタンとラジオボタングループを使う 

ラジオボタンとラジオボタングループを使う 

チェックボックスを使う。 

HTMLのタグの閉じ忘れで例外が発生する!

プルダウンリストとマルチセレクトボックスを使う。

今度はテキストエリアで複数行入力する。 

テキストボックスの入力と基本的なチェックを使う。

 

参照画面・画面遷移に関連する記事

参照画面:テーブルを使い、行毎に色分けした一覧表を表示する。 

参照画面:条件に一致した時のみHTML要素を出力する。

セッションを使って画面間で情報を受け渡す 

画面遷移:GET時のリクエストパラメータを受け取る 

日本語しか使わなくても、i18N対応はする意味がある。

 

入力チェックに関連する記事

入力チェック:未入力時に空文字が渡される仕様を回避する。 

入力チェック:@Patternと正規表現で独自チェックする。

入力チェック:アノテーション定義を自分で作る。(再利用版)

入力チェック用アノテーション定義を自分で作る。(独自実装版)

入力チェック:複数項目の相関チェックアノテーションの作り方

 

データアクセス・その他に関連する記事

データアクセス:Jprepositoryを使って簡単にCRUDする。 

データアクセス:ネイティブなSQL文を実行する 

クラスパス内の静的ファイルにアクセスする 

SpringBootだとログの書き出しも楽ちんです。 

SpringBootプロジェクトでJUNIT4を使った単体テストをする。

 

 

f:id:arakan_no_boku:20170404203859j:plain