今回は、Spring MVC上で、チェック処理を行うプログラムを作成してみたので、そのサンプルプログラムを共有する。
前提条件
下記記事の実装が完了していること。
また、下記サイトのプロパティエディタのインストールが完了していること。
https://www.saka-en.com/eclipse/eclipse-properties-editor-install/
流用ソース
Spring Bootを使っていた、下記記事のソースコードを流用するものとする。
サンプルプログラムの実行結果
下記記事の「完成した画面イメージの共有」と同じ結果となる。ただし、初期表示画面へのアクセスパスは、「http://(サーバー名):(ポート番号)/(プロジェクト名)/」と読み替えること。
サンプルプログラムの作成
作成したサンプルプログラムの構成は以下の通り。
なお、上記の赤枠は、「前提条件」または「流用ソース」のプログラムから変更したプログラムである。
pom.xmlに追加した内容は以下の通りで、Validatorのライブラリ「validation-api」「hibernate-validator」を追加している。それぞれ、古いバージョンだと動かない場合があるため、Spring Bootでサンプル作成時と同じバージョンを指定している。
<!-- Validator --> <dependency> <groupId>javax.validation</groupId> <artifactId>validation-api</artifactId> <version>2.0.1.Final</version> </dependency> <dependency> <groupId>org.hibernate</groupId> <artifactId>hibernate-validator</artifactId> <version>6.0.17.Final</version> </dependency>
また、servlet-context.xmlに追加した内容は以下の通りで、メッセージリソース読み込み定義を追加している。この定義を追加することで、src/main/resources 下のmessages.propertiesが取得できるようになっている。
<!-- メッセージリソースの読み込み --> <beans:bean id="messageSource" class="org.springframework.context.support.ReloadableResourceBundleMessageSource"> <beans:property name="basename" value="classpath:messages" /> <beans:property name="defaultEncoding" value="UTF-8" /> </beans:bean>
さらに、メッセージプロパティの内容は以下の通りで、「流用ソース」と比べ、NotEmptyのメッセージ設定を「javax.validation.constraints.NotEmpty.message=~」⇒「NotEmpty=~」と変更している。
#メッセージ validation.date-empty={0}を入力してください。 validation.date-invalidate=生年月日が存在しない日付になっています。 validation.date-future=生年月日が未来の日付になっています。 validation.empty-msg= NotEmpty={0}を入力してください。 validation.sex-invalidate=性別に不正な値が入っています。 #フィールド名 name=名前 sex=性別 checked=確認チェック
また、CSSファイルの内容は以下の通りで、内容は「流用ソース」そのままで、webapp/resources/static 下に配置場所を変更している。
.errorMessage{ color: #FF0000; } .fieldError{ background-color: #FFCCFF; }
さらに、コントローラクラスの内容は以下の通りで、@GetMapping、@PostMappingアノテーションの代わりに、@RequestMappingアノテーションでmethod属性を指定するようにしている。
package com.example.demo; import org.springframework.stereotype.Controller; import org.springframework.validation.BindingResult; import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.bind.annotation.ModelAttribute; import org.springframework.web.bind.annotation.SessionAttributes; import org.springframework.web.bind.support.SessionStatus; /** * コントローラクラス * 「@SessionAttributes(types = DemoForm.class)」により、 * 生成したFormオブジェクトをセッションとしてもたせている */ @Controller @SessionAttributes(types = DemoForm.class) public class DemoController { /** * Formオブジェクトを初期化して返却する * @return Formオブジェクト */ @ModelAttribute("demoForm") public DemoForm createDemoForm(){ DemoForm demoForm = new DemoForm(); return demoForm; } /** * 入力画面に遷移する * @return 入力画面へのパス */ @RequestMapping(value = "/", method = RequestMethod.GET) public String index(){ return "input"; } /** * エラーチェックを行い、エラーが無ければ確認画面に遷移し、 * エラーがあれば入力画面のままとする * @param demoForm Formオブジェクト * @param result バインド結果 * @return 確認画面または入力画面へのパス */ @RequestMapping(value = "/confirm", method = RequestMethod.POST) public String confirm(@Validated DemoForm demoForm, BindingResult result){ //formオブジェクトのチェック処理を行う if(result.hasErrors()){ //エラーがある場合は、入力画面のままとする return "input"; } //アノテーション以外のチェック処理を行い、画面遷移する return checkOthers(demoForm, result, "confirm"); } /** * エラーチェックを行い、エラーが無ければ完了画面へのリダイレクトパスに遷移し、 * エラーがあれば入力画面に戻す * @param demoForm Formオブジェクト * @param result バインド結果 * @return 完了画面へのリダイレクトパスまたは入力画面へのパス */ @RequestMapping(value = "/send", params = "next", method = RequestMethod.POST) public String send(@Validated DemoForm demoForm, BindingResult result){ //formオブジェクトのチェック処理を行う if(result.hasErrors()){ //エラーがある場合は、入力画面に戻す return "input"; } //アノテーション以外のチェック処理を行い、画面遷移する return checkOthers(demoForm, result, "redirect:/complete"); } /** * 完了画面に遷移する * @param sessionStatus セッションステータス * @return 完了画面 */ @RequestMapping(value = "/complete", method = RequestMethod.GET) public String complete(SessionStatus sessionStatus){ //セッションオブジェクトを破棄 sessionStatus.setComplete(); return "complete"; } /** * 入力画面に戻る * @return 入力画面 */ @RequestMapping(value = "/send", params = "back", method = RequestMethod.POST) public String back(){ return "input"; } /** * アノテーション以外のチェック処理を行い、画面遷移先を返却 * @param demoForm Formオブジェクト * @param result バインド結果 * @param normalPath 正常時の画面遷移先 * @return 正常時の画面遷移先または入力画面へのパス */ private String checkOthers(DemoForm demoForm, BindingResult result, String normalPath){ //** アノテーション以外のチェック処理を行う //** エラーがある場合は、エラーメッセージ・(エラー時に赤反転するための) //** エラーフィールドの設定を行い、入力画面のままとする //生年月日のチェック処理 int checkDate = DateCheckUtil.checkDate(demoForm.getBirthYear() , demoForm.getBirthMonth(), demoForm.getBirthDay()); switch(checkDate){ case 1: //生年月日_年が空文字の場合のエラー処理 result.rejectValue("birthYear", "validation.date-empty" , new String[]{"生年月日_年"}, ""); return "input"; case 2: //生年月日_月が空文字の場合のエラー処理 result.rejectValue("birthMonth", "validation.date-empty" , new String[]{"生年月日_月"}, ""); return "input"; case 3: //生年月日_日が空文字の場合のエラー処理 result.rejectValue("birthDay", "validation.date-empty" , new String[]{"生年月日_日"}, ""); return "input"; case 4: //生年月日の日付が不正な場合のエラー処理 result.rejectValue("birthYear", "validation.date-invalidate"); //生年月日_月・生年月日_日は、エラーフィールドの設定を行い、 //メッセージを空文字に設定している result.rejectValue("birthMonth", "validation.empty-msg"); result.rejectValue("birthDay", "validation.empty-msg"); return "input"; case 5: //生年月日の日付が未来日の場合のエラー処理 result.rejectValue("birthYear", "validation.date-future"); //生年月日_月・生年月日_日は、エラーフィールドの設定を行い、 //メッセージを空文字に設定している result.rejectValue("birthMonth", "validation.empty-msg"); result.rejectValue("birthDay", "validation.empty-msg"); return "input"; default: //性別が不正に書き換えられていないかチェックする if(!demoForm.getSexItems().keySet().contains(demoForm.getSex())){ result.rejectValue("sex", "validation.sex-invalidate"); return "input"; } //エラーチェックに問題が無いので、正常時の画面遷移先に遷移 return normalPath; } } }
他、DateCheckUtil.java、DemoForm.java、HTML各ソースは「流用ソース」と同じ内容となる。そのソースコード内容は、以下のサイトを参照のこと。
https://github.com/purin-it/java/tree/master/spring-mvc-web-check/demo
要点まとめ
- Spring MVCプロジェクトでチェック処理を実装するには、Validatorのライブラリ「validation-api」「hibernate-validator」を追加し、servlet-context.xmlにメッセージリソース読み込み定義を追加する必要がある。
- CSSファイルはWEB-INFディレクトリの外側の、webapp/resources下等に配置する必要がある。