# エラーメッセージをカスタマイズ ## 環境 https://hackmd.io/@ka-777/H1gJjOF__ ↑の続きとなりますのでこの環境が整っていれば今回も大丈夫です。 ## アプリケーションの作成 ### ①プロジェクトの作成 前回説明した手順と同じように作成していきます。 ファイル→新規→Springスターター・プロジェクトを選択します  次にプロジェクト名は好きなのを付けます(今回はspring-mvc3)それ以外のはデフォルトのまま次へを押します  そして今回も依存関係で使うのは前回と同じ5種類です  これでプロジェクトのビルドが完了次第作成終了です。 ### ②モデルの作成 モデルについては前回のところにURLを貼ってあるのでそちらを参照してください 今回もcom.example.demoで右クリックをして新規→クラスでパッケージの語尾に.modelを追加することで以下のように分けることができます  そして今作ったInvoice.javaは以下のように編集します ``` package com.example.demo.model; import java.math.BigDecimal; import java.time.LocalDate; import javax.validation.constraints.Min; import javax.validation.constraints.NotBlank; import javax.validation.constraints.NotNull; import javax.validation.constraints.Pattern; import javax.validation.constraints.Size; import org.springframework.format.annotation.DateTimeFormat; import org.springframework.format.annotation.DateTimeFormat.ISO; import org.springframework.format.annotation.NumberFormat; import lombok.Getter; import lombok.Setter; @Getter @Setter public class Invoice { //必須入力、文字列が30文字まで @NotBlank @Size(max = 60) private String name; //必須入力、文字列が100文字まで @NotBlank @Size(max = 100) private String address; //必須入力、半角数字かハイフンのみ @NotBlank @Pattern(regexp = "[0-9-]*") private String phoneNumber; //必須入力、1000円以上、数値へ変換 @NotNull @Min(1000) //patternで#のところに数値が入るので形を指定できる @NumberFormat(pattern = "#,###") private BigDecimal price; //必須入力、日付へ変換 @NotNull //iso = ISO.DATEはpattern="yyyy-MM--dd"と同じ意味です @DateTimeFormat(iso = ISO.DATE) private LocalDate paymentDeadline; } ``` 今回もアノテーションを使い簡単にフォームの入力項目の制限を作ることができます ### ③コントローラの作成 モデルと同じように「com.example.demo」を右クリック→新規→クラスでパッケージの語尾に.controllerを追加し、名前は好きなのをつける(controllerを付けておくとほかの人もわかりやすい)今回はHomeControllerでやります  そして作成し終わったらHomeController.javaを以下のように編集します ``` package com.example.demo.controller; import org.springframework.stereotype.Controller; import org.springframework.validation.BindingResult; import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.ModelAttribute; import org.springframework.web.bind.annotation.PostMapping; import com.example.demo.model.Invoice; @Controller public class HomeController { @GetMapping("/") public String index(@ModelAttribute Invoice invoice) { return "index"; } @PostMapping("/") public String confirm(@Validated @ModelAttribute Invoice invoice, BindingResult result) { if(result.hasErrors()) { return "index"; } return "confirm"; } } ``` 今回は前回で説明したものしか使っていないので説明は割愛しますがGetMappingやPostMappingの("")は好きなのを入力してもらって大丈夫です。アクセスする際のアドレスが/から入力したものに変わるだけです(今回はわかりやすく/のみにしています)例えばindex.htmlは今回もフォーム入力形式なのでアドレスを/formにしてフォーム入力なのをわかりやすくするのもありです ### ④Bootstrapの追加 前回説明したBootstrapを使うための準備をしていきます。 プロジェクト直下にあるpom.xmlを前回同様編集します ※必ずdependenciesタグの中にいれてください  ``` <!-- dependenciesタグ内に追加 --> <dependency> <groupId>org.webjars</groupId <artifactId>bootstrap</artifactId> <version>4.5.3</version> </dependency> <dependency> <groupId>org.webjars</groupId> <artifactId>webjars-locator</artifactId> <version>0.40</version> </dependency> ``` ### ⑤htmlの作成 htmlをいつも通り作成する方法は「src/main/resources」を右クリックして新規→その他を選択する  ファイル名はcontrollerで指定したアドレスを入力してください  そして新規作成したindex.htmlを編集していきます ``` <!DOCTYPE html> <html xmlns:th="http://wwww.thymeleaf.org"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width,initial-scale=1"> <link rel="stylesheet" th:href="@{/webjars/bootstrap/css/bootstrap.min.css}"> <title>Title</title> </head> <body class="bg-light"> <div class="container"> <div class="row justify-content-md-center"> <div class="col-md-8"> <h4 class="border-bottom my-3" th:text="#{invoice}"> </h4> <form th:action="@{/}" th:object="${invoice}" method="POST" novalidate> <div class="form-group"> <label for="name" th:text="#{name}"></label> <input type="text" class="form-control" th:errorclass="is-invalid" th:field="*{name}"> <div class="invalid-feedback" th:errors="*{name}"> </div> </div> <div class="form-group"> <label for="address" th:text="#{address}"></label> <input type="text" class="form-control" th:errorclass="is-invalid" th:field="*{address}"> <div class="invalid-feedback" th:errors="*{address}"> </div> </div> <div class="form-group"> <label for="phone" th:text="#{phoneNumber}"></label> <input type="tel" class="form-control" th:errorclass="is-invalid" th:field="*{phoneNumber}"> <div class="invalid-feedback" th:errors="*{phoneNumber}"> </div> </div> <div class="form-group"> <label for="price" th:text="#{price}"></label> <input type="text" class="form-control" th:errorclass="is-invalid" th:field="*{price}"> <div class="invalid-feedback" th:errors="*{price}"> </div> </div> <div class="form-group"> <label for="paymentDeadline" th:text="#{paymentDeadline}"></label> <input type="tel" class="form-control" th:errorclass="is-invalid" th:field="*{paymentDeadline}"> <div class="invalid-feedback" th:errors="*{paymentDeadline}"> </div> </div> <button class="btn btn-primary btn-lg btn-block my-4" type="submit" th:text="#{register}"> </button> </form> </div> </div> </div> <script th:src="@{/webjars/jquery/jquery.min.js}"></script> <script th:src="@{/webjars/popper.js/umd/popper.min.js}"></script> <script th:src="@{/webjars/bootstrap/js/bootstrap.min.js}"></script> </body> </html> ``` 今回も特に新しい内容はないので説明は割愛します 次にconfirm.htmlを作成していきます 作成手順はindex.htmlと同じです。 ``` <!DOCTYPE html> <html xmlns:th="http://www.thymeleaf.org"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width,initial-scale=1"> <link rel="stylesheet" th:href="@{/webjars/bootstrap/css/bootstrap.min.css}"> <title>Title</title> </head> <body class="bg-light"> <div class="container"> <div class="row justify-content-md-center"> <div class="col-md-8"> <h4 class="border-bottom my-3" th:text="#{invoice}"> </h4> <p class="text-danger" th:text="#{confirmationMessage}"></p> <div th:object="${invoice}"> <div class="form-group"> <label for="name" th:text="#{name}"></label> <input type="text" class="form-control" th:field="*{name}" disabled> </div> <div class="form-group"> <label for="address" th:text="#{address}"></label> <input type="text" class="form-control" th:field="*{address}" disabled> </div> <div class="form-group"> <label for="phoneNumber" th:text="#{phoneNumber}"></label> <input type="tel" class="form-control" th:field="*{phoneNumber}" disabled> </div> <div class="form-group"> <label for="price" th:text="#{price}"></label> <input type="text" class="form-control" th:field="*{price}" disabled> </div> <div class="form-group"> <label for="paymentDeadline" th:text="#{paymentDeadline}"></label> <input type="date" class="form-control" th:field="*{paymentDeadline}" disabled> </div> </div> </div> </div> </div> <script th:src="@{/webjars/jquery/jquery.min.js}"></script> <script th:src="@{/webjars/popper.js/umd/popper.min.js}"></script> <script th:src="@{/webjars/bootstrap/js/bootstrap.min.js}"></script> </body> </html> ``` confirm.htmlも新しいのはないので説明は割愛します ### ⑥エラーメッセージの編集 エラーメッセージを1つ1つのフォームによってかえるために新しくクラスを作っていきます 今回も新しく.configをつけることによってModel等のように誰が見てもわかりやすくできます   また、MessageConfig.javaは以下のように編集します ``` package com.example.demo.config; import org.springframework.context.MessageSource; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.context.support.ReloadableResourceBundleMessageSource; import org.springframework.validation.beanvalidation.LocalValidatorFactoryBean; @Configuration public class MessageConfig { @Bean public MessageSource messageSource() { var source = new ReloadableResourceBundleMessageSource(); //読み込むメッセージファイルを指定します source.setBasenames("classpath:i18n/messages","classpath:i18n/ValidationMessages"); //メッセージの文字コードをUTF-8にします source.setDefaultEncoding("UTF-8"); //システムの言語に関係なく、デフォルトのメッセージを返せるようにする source.setFallbackToSystemLocale(false); return source; } @Bean public LocalValidatorFactoryBean getValidator() { //上のmessageSource()メソッドをセットします var bean = new LocalValidatorFactoryBean(); bean.setValidationMessageSource(messageSource()); return bean; } } ``` 本来このような設定はXMLで定義しないといけないがアノテーション(@Beanや@Configuration)によってJavaだけで設定することができます ### ⑦エラーメッセージを追加 「src/main/resources」に新しいファイル「i18n」を作ります(ここは先ほどMessageCongig.javaで指定したアドレスのフォルダ名です)  そして新規作成したフォルダの中に以下の4つのファイルを作成します  ここのmessagesのほうThymeleafで使うメッセージを記述して、Valiのほうはカスタマイズするエラーメッセージを記述しています 今回もjaファイルは日本語用なので言語をUTF-8に変更します   また、エラーメッセージはまとめてコードを載せておきます ↓messages_ja.properties ``` invoice = 請求書 name = お客様名 address = 住所 phoneNumber = 電話番号 price = 金額(円) paymentDeadline = 支払い期日 register = 登録 confirmationMessage = 登録が正常に完了しました ``` ↓messages.properties ``` invoice = Invoice name = Name address = Address phoneNumber = Phone number price = Price (JPY) paymentDeadline = Payment deadline register = Register confirmationMessage = Registration has been successfully completed ``` ↓ValidationMessages_ja.properties ``` # 個別メッセージ Pattern.invoice.phoneNumber = {0} は、半角の数字かハイフンで入力してください(例: 03-1234-5678) Min.invoice.price = {0}は、{1}円以上の値を入力してください # 共通メッセージ NotBlank = {0}を入力してください NotNull = {0}を入力してください Size = {0}は、{2}文字以上、{1}文字以下で入力してください Min = {0}は,{1}以上の値を入力してください # typeMismatch:個別メッセージ typeMismatch.invoice.price = {0}が不正な値です typeMismatch.invoice.paymentDeadline = {0}は、"2020-01-01"形式で入力してください ``` ↓↓ValidationMessages.properties ``` # Individual messages Pattern.invoice.phoneNumber = {0} must be a half-width number or hyphen (e.g. 03-1234-5678) Min.invoice.price = {0} must be greater than or equal to {1} JPY #Common messages NotBlank = {0} is required NotNull = {0} is required Size = {0} must be between {2} and {1} characters Min = {0} must be greater than or equal to {1} # typeMismatch:Individual messages typeMismatch.invoice.price = {0} is incorrect typeMismatch.invoice.paymentDeadline = {0} must be in "2020-01-01" format ``` {0}と書かれているところはそこに項目名が入ったりしてくれるため全部のエラーをまとめて管理することができる 例えば、名前のところに入力にミスがあると{0}のところにお客様名(messagesに入っている)と表示してくれる ### ⑧ようやく実行 ここまで長かったですが前回同様「com.example.demo」にあるSpringmvc3Application.javaを右クリック→実行→Spring Boot アプリを押せば完了です そしてエラーもなく実行できた場合は[ここ](http://localhost:8080/)(http://localhost:8080/) にアクセスすると入力フォームの画面になります 実行した後に入力フォームで値を入力しなかったり、規定以外のことをすると今まで設定した細かいエラーメッセージまで出力してくれます ## まとめ こんな簡単なアプリケーションでもエラーメッセージの処理をしっかりやるだけでかなり実用的な見た目になると思います 今回も長くなりましたが以上です 誤字脱字、スクリプトのミスがあれば指摘してくださると助かります
×
Sign in
Email
Password
Forgot password
or
By clicking below, you agree to our
terms of service
.
Sign in via Facebook
Sign in via Twitter
Sign in via GitHub
Sign in via Dropbox
Sign in with Wallet
Wallet (
)
Connect another wallet
New to HackMD?
Sign up