今回は、Spring MVC上で、チェック処理を行うプログラムを作成してみたので、そのサンプルプログラムを共有する。
前提条件
下記記事の実装が完了していること。
また、下記サイトのプロパティエディタのインストールが完了していること。
https://www.saka-en.com/eclipse/eclipse-properties-editor-install/
流用ソース
Spring Bootを使っていた、下記記事のソースコードを流用するものとする。
サンプルプログラムの実行結果
下記記事の「完成した画面イメージの共有」と同じ結果となる。ただし、初期表示画面へのアクセスパスは、「http://(サーバー名):(ポート番号)/(プロジェクト名)/」と読み替えること。
サンプルプログラムの作成
作成したサンプルプログラムの構成は以下の通り。
なお、上記の赤枠は、「前提条件」または「流用ソース」のプログラムから変更したプログラムである。
pom.xmlに追加した内容は以下の通りで、Validatorのライブラリ「validation-api」「hibernate-validator」を追加している。それぞれ、古いバージョンだと動かない場合があるため、Spring Bootでサンプル作成時と同じバージョンを指定している。
1 2 3 4 5 6 7 8 9 10 11 | <!-- 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が取得できるようになっている。
1 2 3 4 5 | <!-- メッセージリソースの読み込み --> <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=~」と変更している。
1 2 3 4 5 6 7 8 9 10 11 12 | #メッセージ 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 下に配置場所を変更している。
1 2 3 4 5 6 | .errorMessage{ color: #FF0000; } .fieldError{ background-color: #FFCCFF; } |
さらに、コントローラクラスの内容は以下の通りで、@GetMapping、@PostMappingアノテーションの代わりに、@RequestMappingアノテーションでmethod属性を指定するようにしている。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 | 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下等に配置する必要がある。