TERASOLUNA
では、いくつかの入力チェックの方法が用意されています。
5.5章の入力チェック
を参考に、情報をざっくりまとめてみたいと思います。
---
5.5.1. Overview
長さや形式など、文脈によらず入力値だけを見て、それが妥当かどうかを判定できる検証
→「入力チェック」
システムの状態によって入力値が妥当かどうかが変わる検証
→「業務ロジックチェック」
と定義し、前者の入力チェックについて説明します(後者はドメイン層の実装
をみてね)、とあります。
サーバサイドの入力チェックとクライアントサイドの入力チェックについて、以下のような言及をしています。
・サーバサイドの入力チェック:必須(JavaScripによる改ざん防止のため)
・クライアントサイドの入力チェック:ユーザビリティの向上
5.5.1.1. 入力チェックの分類
単項目チェックと相関項目チェックがあり、特徴を表でまとめています。
単項目は単一項目でのチェック、相関項目は複数項目に相関するチェックという感じです。
実現方法は以下の通りです。
・単項目チェックは「BeanValidation」を使用 (実装ライブラリとしてHibernate Validatorを使用)
・相関項目チェックは、「org.springframework.validation.Validator
インタフェースを実装したValidationクラス」または「BeanValidation」を使用
5.5.2.1. 依存ライブラリの追加
アプリケーションサーバにデプロイして動かす場合は依存ライブラリは追加しなくてよいとのこと。
スタンドアロン環境(JUnitなど)で動かす場合は、これらのライブラリを依存ライブラリとして追加する必要があるとのこと。
必要なものはTERASOLUNAの5.5.2.1
を参照ください。
5.5.2.2. 単項目チェック
単項目チェックするには、3ヶ所に対して手を施す必要があるそうです。
フォームクラスのフィールドに、Bean Validation用のアノテーションを付与する
Controllerに、検証するための@Validated アノテーションを付与する
JSPに、検証エラーメッセージを表示するためのタグを追加する
アノテーションを付与する、という表現に関しては後述にて説明します。
5.5.2.2.1. 基本的な単項目チェック
フォームクラス、Controller、JSPについての例が記載されています。
----
フォームについては、下記Appendixを参考にアノテーションを付与してね、と言ってます。
5.5.4.1. Hibernate Validatorが用意する入力チェックルール
5.5.4.1.1. Bean Validationのチェックルール
5.5.4.1.2. Hibernate Validatorのチェックルール
これらのうち、ガイドラインの例では、@NotNull、@Size、@Email、@Min、@Maxを使ってます。
で、この@なんちゃらをアノテーション と呼んでいます。
アノテーションを付与するとは、宣言の前に@なんちゃらを記載することと捉えます。
ガイドラインの以下の例では、 private String name ; の前に、@NotNullと@Sizeが記載されていますね。
付与することにより、様々な入力チェックを実施してくれます。
Hibernate Validatorが準備しているアノテーションの種類と入力チェック内容が、上記Appendixに記載されています。
----
Contollerについては、入力チェック対象のフォームクラスに@Validated を付けてね、と言ってます。
黄色の部分、UserFormの前に@Validated がありますね。
----
JSPについては、<form:errors> タグで入力エラーがある場合にエラーメッセージを表示できますよ、と言ってます。
各入力フォームにタグを指定して・・・
すべての入力フィールドを未入力のまま送信すると、以下のようにエラーメッセージが表示されるよ、という例が記載されています。
また、cssを変更することによりエラーメッセージの出力方法を変えられる、とも言っています。
上記のように一覧で表示する場合「標準では出力順序を制御できないから、入力フィールドの横にエラーメッセージを出すことを推奨する」とあるけども
入力項目が多い場合とか他の画面との一体感の兼ね合いで、必ずしもそうではない、とは思ったりします。
5.5.2.2.2. ネストしたBeanの単項目チェック
基本的には
・Formのすべての項目にアノテーションを用意して
・JSPのすべての項目に<form:errors>タグを付ける
というのが上記の例です。
しかし、あるFormAから別のFormBを複数呼び出すときに
ネスト先のFormBの項目にアノテーションを付与すれば、FormA側のアノテーション宣言は不要になります、と言っています。
例えば、注文フォームに送り元住所と送り先住所があり、それぞれ同じ入力項目欄を準備する場合
住所フォームを用意し、送り元と送り先に同じ住所フォームを用いるのが一般的かと思いますが
その住所フォームにアノテーションを用意すれば、送り元と送り先それぞれの各項目に
アノテーションを付与したのと同じになります。
ただし、JSP側は全ての項目に設定が必要で、更に場合によっては
各FormBのすべてのパラメータが送信されなかった場合の<form:errors>タグを準備するなど
逆に手間がかかってしまう場合があるので、注意が必要です。
5.5.2.2.3. バリデーションのグループ化
・一つのフィールドに対して、グループごとに入力チェックルールを決められる「バリデーショングループ」を作れます。
・FormにグループごとのInterfaceを準備します。
・アノテーションリストを作り、そのリストの1つ1つにグループの条件を追加します。
・Controllerで、どの入力のときにどの条件を使うかを明示します。大きな変更になります。
・JSPはグループを判断できる入力項目があればよく、大きな変更は不要です。
5.5.2.3. 相関項目チェック
SplingValidatorとBeanValidatorのメリット、デメリットが記載していますが、メリットを抜き出すと以下になります。(もう片方に書いてあることがしづらいのがデメリット、という認識で)
・SplingValidator
特定のクラスに対する入力チェックの作成が容易
特定のフォームに依存した業務要件固有の入力チェック実装に向いている
・BeanValidator
Controllerでの利用が容易
特定のフォームに依存しない、開発プロジェクト共通の入力チェック実装に向いている。
5.5.2.3.1. Spring Validatorによる相関項目チェック実装
「パスワードリセット」処理を例に実装方法を説明しています。
Validatorクラスを作って、Controllerクラスで宣言します。
■Validatorクラス
・チェック対象以外のクラスは処理しないような実装とする。
・単項目チェックでひっかかったときにチェックしないようなら、そのような実装もする。
・チェックロジックを実装する。
・エラーが表示されるフィールド(場所)を実装する。
・エラーメッセージ(コードとデフォルト)を実装する。
■Controllerクラス
・Validatorをインジェクションする。
(インジェクションする・・・直訳すれば注入するとか注射するとかですが、要は「機能を有効にするための記載を加える」ぐらいの認識でよいかと)
・@InitBinderをアノテーションして、作成したValidatorを追加する。
5.5.2.3.2. Bean Validationによる相関項目チェック実装
(5.5.3. How to extend)
Bean Validationによって、相関項目チェックの実装するためには、独自バリデーションルールの追加を行う必要がある。
大きく、以下の2つの観点に分かれる
・既存ルールを組み合わせ
・新規ルールを実装
5.5.3.1. 既存ルールを組み合わせたBean Validationアノテーションの作成
・エラーメッセージの共通化をしたいときなどに有用
5.5.3.2. 新規ルールを実装したBean Validationアノテーションの作成
・javax.validation.ConstraintValidator インタフェースを利用し、任意のルールを作ります。
5.5.3.2.1. 既存のルールの組み合わせでは表現できないルール
・ConstraintValidatorを継承したValidatorと、それを使用するアノテーションを作成します。
・アノテーション内に、表現したいルールを実装します。
5.5.3.2.2. 相関項目チェックルール
・ConstraintValidatorを継承したValidatorと アノテーション、フォームを作成する。
・相関項目チェック用のアノテーションはクラスレベルに付与できるようにします。
・フォームのクラスレベルに作成したアノテーションを付与する。
・Spring Validatorによる相関項目チェック実装で用いた InitBinderの宣言は不要
5.5.3.2.3. 業務ロジックチェック
(コピペです)
一方で、「入力されたユーザー名が既に登録済みかどうか」など、対象の入力フィールドに対する業務ロジックエラーメッセージを、フィールドの横に表示したい場合もある。 このような場合は、ValidatorクラスにServiceクラスをインジェクションして、業務ロジックチェックを実行し、その結果を、ConstraintValidator.isValid の結果に使用すればよい。
5.5.2.4. エラーメッセージの定義
Springのルール、BeanValidationのルールがあり、Springのほうが優先される。
Springの場所はここ。
5.5.2.4.1. ValidationMessages.propertiesに定義するメッセージ
javax.validation.constraints.Size.message = size is not in the range {min} through {max}.
のように、属性値の埋め込みが可能
javax.validation.constraints.Min.message = can not be less than {value}.
のように、不正となった入力値は、{value} で埋め込むことができる。
org.hibernate.validator.constraints.Email.message = "{0}" is an invalid e-mail address.
のように、フィールド名は{0}で埋め込むことができる。
5.5.2.4.2. application-messages.propertiesに定義するメッセージ
ValidationMessages.を上書きたい場合に使用。
アノテーション名.フォーム属性名.プロパティ名 = 対象のメッセージ
====================
というわけで、(コピペもありますが)TERASOLUNAの入力チェックについてのまとめですた。