SpringBoot+thymeleafで、テキストボックスの入力とバリデーションをやります。
STS3(3.9.6)+SpringBoot2.0+Tymeleaf3.0迄動作確認しています。
入力画面サンプル
簡単なIDとパスワードとコメントを入力する画面にします。
Formクラス
最初にリクエストとレスポンスで受け渡しをする項目をFormクラスに定義します。
以下のようなFormクラスを定義します。
PIDをinputPid、Password をinputPwdという名前にしています。
public class Hello3Form implements Serializable {
private static final long serialVersionUID = 109090L;
@NotNull
@Size(min = 1)
private String inputPid;@Size(min = 6,max=20)
private String inputPwd;}
長くなるので、getterとsetterは省略してますが、実装する時には追加してください。
項目にアノテーションを付与して、入力チェックができるので、使ってみます。
標準アノテーションを表にしてみました。
今回は必須入力チェックとして@NotNullと文字数指定の@Sizeだけ使います。
@NotNullの注意
@NotNullの利用には注意が必要です。
これはNullはエラーにしますが、空文字(””)は通します。
実は、テキストボックスの初期表示状態のまま何も入力しない時は空くても、空文字(””)を通すので、必須チェックにひっかかりません。
2017/3/25追記
回避する方法はあります。
その方法はこちらで解説しています。
今回は暫定対応として、@NotNull以外に@Size(min=1)をつけてます。
エラーメッセージ
今度はエラーメッセージを表示するためにメッセージを定義します。
使うための設定はこちらの記事をを参照してください。
src/main/resources/messages.propertiesに以下を追記します。
NotNull={0}は必須入力です。
Size={0}は{2}文字以上、{1}文字以下で入力してください。
Size.inputPid={0}は必須入力です。
エラーメッセージは、アノテーションの名前で定義すれば良いです。
@Sizeのように2つの項目にまたがって指定した時は、「アノテーション名+Formクラスで定義した変数名」で、指定の項目のみに適用するメッセージを定義します。
Sizeのエラーメッセージで、{1}にはmax、{2}にはminの指定値がはいりますが、(min=1,max=10)のように指定した順番ではなく、パラメータ名(max,min)のソート順で小さい方から1,2と番号が振られる点も勘違いしやすいので注意してください。
コントローラクラス
ポイントだけ引用します。
@RequestMapping(value = "/hello3", method = RequestMethod.GET)
public String index(Hello3Form form, Model model) {
model.addAttribute("hello3Form", form);
return "hello3";
}
@RequestMapping(value = "/outpg01", method = RequestMethod.POST)
public String confirm(@Validated @ModelAttribute Hello3Form form, BindingResult result, Model model) {
if (result.hasErrors()) {
return index(form, model);
}
return "outpg01";
}
ちょっと解説します。
初期表示に対応する index()メソッドと、画面で入力後の実行ボタンに対応するconfirmメソッドを定義します。
indexメソッドで「value = "/hello3"」として、例えば、http://localhost/hello3 の様に画面表示できるようにします。
この時、model.addAttribute("hello3Form", form); のように、HTML側のth:objectでフォームを認識し、値を参照できるようにします。
2018/3/11追記
>これを忘れると以下のようなエラーがでます。(通っても・・たまたまです)
>「Neither BindingResult nor plain target object for bean name 'XxxxxForm' available as request attribute」
>「Error during execution of processor 'org.thymeleaf.spring5.processor.SpringInputGeneralFieldTagProcessor」
その画面のsubmitボタンが押された時に対応するメソッドは、confirmです。
その対応づけをするために「value = "/outpg01"」と定義して、HTMLからは/outpg01でアクセスできるようにしておきます。
リクエストとレスポンスで値の受け渡しをするために定義したFormクラスを、それぞれに「Hello3Form」として指定しています。
confirm()では、result.hasErrors()をチェックすることで、入力チェックでエラーがあったかどうかをみています。
エラーがあれば index()を読んで再度 hello3ページに遷移し、エラーがなければ結果表示画面のoutpg01をに遷移する。・・とまあ、こんな感じです。
入力画面:HTML+Tymeleaf
class属性の指定などは省略して書いてます。
入力画面 hello3.htmlの一部です。
<form role="form" action="/outpg01" th:action="@{/outpg01}" th:object="${hello3Form}" method="post"> <p th:text="#{please.pid}">Please input PID</p> <input type="text" th:field="*{inputPid}" /> <span th:if="${#fields.hasErrors('inputPid')}" th:errors="*{inputPid}">error!</span> <br /> <p th:text="#{please.pwd}">Please input PID</p> <input type="password" th:field="*{inputPwd}" /> <span th:if="${#fields.hasErrors('inputPwd')}" th:errors="*{inputPwd}">error!</span><br /> <button type="submit">実行</button> </form>
<form role="form" action="/outpg01" th:action="@{/outpg01}" th:object="${hello3Form}" method="post">の部分を補足します。
th:actionで、コントローラークラスでconfirm()めセッドで定義する/outpg01、th:objectで、Formクラスの名前(先頭は小文字)を指定します。
こうすることで、Submitでconfirm()メソッドが呼ばれるようになります。
<input type="text" th:field="*{inputPid}" /> は、テキストボックスの値をFormのinputPidに対応されるよということです。
そして、<span th:if="${#fields.hasErrors('inputPid')}" th:errors="*{inputPid}">error!</span>で、項目ごとのエラーメッセージの表示の制御をしています。
出力画面:HTML+Tymeleaf
<div th:object="${hello3Form}">
<p th:text="*{inputPid}"></p>
<p th:text="*{inputPwd}"></p>
</div>
Div タグの th:objectでFormを指定して、その内側で、Formの項目の値を参照するわけです。
一旦動かします。
SpringBootアプリケーションを実行して、/hello3を表示します。
エラーを出したいので、PIDには何も入力せず、パスワードに1文字だけ入力して実行ボタンを押します。
想定通りにエラーが表示されました。
今度は、エラーにならないように入力して、実行ボタンを押します。
入力したとおりに、outpg01画面が表示されたので、基本的な動きはOKみたいです。
STS+Spring Boot+thymeleaf 関連記事
入力画面に関連する記事
参照画面・画面遷移に関連する記事
参照画面:テーブルを使い、行毎に色分けした一覧表を表示する。
入力チェックに関連する記事
入力チェック:@Patternと正規表現で独自チェックする。
入力チェック用アノテーション定義を自分で作る。(独自実装版)
データアクセス・その他に関連する記事