Spring Bootで入力値の検証をします。
基本
Bean Validationが使えるみたいです。
Using Bean Validation - The Java EE 6 Tutorial
ということで、以下のようなクラスを作ってアノテーションをつけるだけでOK。
package helloboot.modelattr.controllers; import javax.validation.constraints.Pattern; import org.hibernate.validator.constraints.NotEmpty; publicclass PersonForm { @NotEmpty(message = "{name}") private String name; @NotEmpty(message = "{age}") @Pattern(regexp = "[0-9]*", message="数字で入力してください") private String age; public String getName() { return name; } publicvoid setName(String name) { this.name = name; } public String getAge() { return age; } publicvoid setAge(String age) { this.age = age; } }
messageにエラーメッセージを指定するのですが、このとき普通に文字列を渡してもいいし{key}のような書き方をするとValidationMessages.propertiesからエラーメッセージをひっぱってくるようにもできます。国際化も楽ちんですね。
因みにValidationMessages.propertiesは以下のような感じにしました。
age=age error! name=name error!
コントローラでのエラーハンドリング
コントローラでバリデーションの結果を受け取るには以下のようにします。
- @ValidアノテーションをFormクラスにつける
- BindingResultインターフェースを@Validを付けたパラメータのすぐ後ろに追加する
メソッドの定義はこんな感じ。
public String post(@ModelAttribute("form") @Valid PersonForm form, BindingResult bindingResult)
bindingReusltのhasErrorsメソッドでエラーの有無が確認できます。フィールド単位のエラーが欲しかったら、hasFieldErrorsを使います。getAllErrors, getFieldErrorsでエラーを取得します。getAllErrorsやgetFieldErrorsメソッドの戻り値はList>ObjectError<でgetDefaultMessageでエラーメッセージを取得できます。
こんな感じで。
@RequestMapping(name = "/", method = { RequestMethod.POST }) public String post(@ModelAttribute("form") @Valid PersonForm form, BindingResult bindingResult) { for (ObjectError error : bindingResult.getAllErrors()) { System.out.println(error.getDefaultMessage()); } return"index"; }
Thymeleafでのエラーの処理
最終的に画面でエラーを出す方法は以下のような感じです。
#fieldsを使ってエラー情報を取得します。detailedErrorsですべてのエラーを取得できます。こんな感じで。th:objectでエラーをとりたいオブジェクトを設定してる点ポイントです。
<body th:object="${form}"><ul><li th:each="error : ${#fields.detailedErrors()}"><span th:text="${error.message}">Error message</span></li></ul> ... </body>
次に入力フィールドの横とかにエラーを出したい場合の書き方です。
<span th:if="${#fields.hasErrors('name')}" th:errors="*{name}">Name error</span>
エラーの時だけスタイルを切り替えたいときとかはth:errorclassを使います。
</label><inputname="name"type="text" th:field="*{name}" th:errorclass="error-field"/>
エラーが1つもないときだけ表示したい項目は以下のようにかけました。(もっとスマートな書き方があるかも)
<div th:if="${#arrays.length(#fields.detailedErrors())} == 0"> ...ここにエラーがないときに出したい項目を書く... </div>