SpringBoot:エラーメッセージを表示
以下のことを実施します。
1.エラーメッセージを表示する。
2.メッセージの国際化対応
3.Webjarsを使用
依存関係は以下の通り
・Spring Boot Dev Tools
・Lombok
・検証
・Thymeleaf
・Spring Web
モデルの作成
@NotBlankや@Sizeはバリデーション用のアノテーション。
これらを使用することでエラーチェックを簡単に実装できる
package com.example.demo;
import javax.validation.constraints.Email;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.Size;
import lombok.Getter;
import lombok.Setter;
@Getter
@Setter
public class Inquiry {
@NotBlank
@Size(max=60)
private String name;
@NotBlank
@Email
@Size(max = 254)
private String email;
@NotBlank
@Size(max=500)
private String inquiry;
}
コントローラを作成
@Validated
入力値のチェックを行う
チェックの結果は、BindingResultに入るので
result.hasErrors()でエラーがあるか確認できる
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.GetMapping;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.PostMapping;
@Controller
public class HomeController {
@GetMapping("/")
public String index(@ModelAttribute Inquiry inquiry) {
return"index";
}
@PostMapping("/")
public String confirm(@Validated@ModelAttribute Inquiry inquiry, BindingResult result) {
if(result.hasErrors()) {
return"index";
}
return"confirm";
}
}
Bootstrapを追加
・Bootstrapとは
BootstrapはCSSやjavaScriptから構成されるフレームワーク
きれいな画面がつくれることやPCやスマートフォンなどに自動対応する画面
が作れる。
・pom.xmlを編集
dependenciesタグ内に以下の2つを追加
<dependency>
<groupId>org.webjars</groupId>
<artifactId>bootstrap</artifactId>
<version>4.5.0</version>
</dependency>
<dependency>
<groupId>org.webjars</groupId>
<artifactId>webjars-locator</artifactId>
<version>0.40</version>
</dependency>
Thymeleafを作成
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="contatiner">
<div class="row justify-content-md-center">
<div class="col-md-8">
<h4 class="border-bottom my-3" th:text="#{inquiry}"></h4>
<form th:action="@{/}" th:object="${inquiry}"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="email" th:text="#{email}"></label>
<input type="email" class="form-control" th:errorclass="is-invalid" th:field="*{email}">
<div class="invalid-feedback" th:errors="*{email}"></div>
</div>
<div class="form-group">
<label for="inquiry" th:text="#{inquiry}"></label>
<textarea class="form-control" rows="3" th:errorclass="is-invalid" th:field="*{inquiry}"></textarea>
<div class="invalid-feedback" th:errors="*{inquiry}"></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:sec="@{/webjars/bootstrap/js/bootstrap.min.js}"></script>
</body>
</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="@{/webjar/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="#{inquiry}"></h4>
<p class="text-danger" th:text="#{confirmationMessage}"></p>
<div th:object="${inquiry}">
<div class="form-group">
<label for="password" th:text="#{name}"></label>
<input type="text" class="form-control"th:field="*{name}" disabled>
</div>
<div class="form-group">
<label for="email" th:text="#{email}"></label>
<input type="email" class="form-control" th:field="*{email}"disabled>
</div>
<div class="form-group">
<label for="inquiry" th:text="#{inquiry}"></label>
<textarea class="form-control" rows="3" th:field="*{inquiry}"disabled></textarea>
</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>
メッセージの国際化対応
messages_ja.prpertiesとmessages.propertiesを作成し以下のように編集する
・messages.ja.properties
inquiry=お問い合わせ
name=お名前
email=Email
register=登録
confirmationMessage=以下の内容で登録が完了しました。
・messages.properties
inquiry=Inquiry
name=Name
email=Email
register=Register
confimationMessage=Registration has been completed with the following
確認
ブラウザでhttp://localhost:8080/を開き文字を入力後登録ボタンを押下
また、空欄の状態で登録ボタンを押下しエラーメッセージが表示されるか確認
エラーメッセージをカスタマイズする
以下のことを実施します。
・エラーメッセージをカスタマイズする
・国際化メッセージを設定する
依存関係
・Spring Boot Dev Tools
・Lombok
・検証
・Thymeleaf
・Spring Web
モデルの作成
@NumberFomat(@pattern="#,###")
指定パターンの文字列を数値に型変換します。
@DateTimeFormat(iso = ISO.DATE)
ISOパターンの文字列を日付に型変換します。
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 {
@NotBlank
@Size(max=60)
private String address;
@NotBlank
@Pattern(regexp ="[0-9-]*")
private String phoneNumber;
@NotNull
@Min(1000)
@NumberFormat(pattern="#,###")
private BigDecimal price;
@NotNull
@DateTimeFormat(iso=ISO.DATE)
private LocalDate paymentDeadline;
}
コントローラ作成
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";
}
}
Bootstrapを追加
pom.xmlを開き以下を追加
<dependency>
<groupId>org.webjars</groupId>
<artifactId>bootstrap</artifactId>
<version>4.5.0</version>
</dependency>
<dependency>
<groupId>org.webjars</groupId>
<artifactId>webjars-locator</artifactId>
<version>0.40</version>
</dependency>
Thymeleafを作成
<!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="contatiner">
<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="date"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>
登録完了画面作成
<!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 order-md-1">
<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>
メッセージコンフィグ作成
@configuration
設定クラスであることを示す
@bean
Springに管理されるBeanの生成を示す。
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");
source.setDefaultEncoding("UTF-8");
source.setFallbackToSystemLocale(false);
return source;
}
@Bean
public LocalValidatorFactoryBean getValidator() {
var bean = new LocalValidatorFactoryBean();
bean.setValidationMessageSource(messageSource());
return bean;
}
}
メッセージを追加
以下のファイルを作成後編集
・messages_jp.properties
invoice=請求書
name=お客様名
address =住所
phoneNumber=電話番号
price = 金額
paymentDeadline =支払期日
register =登録
confirmationMessage =登録が正常に完了しました。
・messages.properties
invoice = Invoice
name = Name
address = Address
phoneNumber = Phone number
price = Price
paymentDeadline = Payment deadline register = Register
confirmationMessage = Registration has been successfully completed
・ValidationMessages_ja.properrties
# 個別メッセージ
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.paymentDealine={0}は"2020-01-01"形式で入力してください。
・ValidationMessages.properties
# Individual messages
Pattern.invoice.phoneNumber ={0} must bea half-width numver 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