入力検証処理追加
「登録機能作成」で作成した機能に入力チェック処理を追加する。
1. ライブラリ追加
build.gradleのdependencies{}にspring-boot-starter-validationを追加する。
/demo/build.gradle
dependencies {
... 略 ...
implementation 'org.springframework.boot:spring-boot-starter-validation'
}
2. 検証エラーメッセージ
今回はValidationMessages.propertiesファイルに以下のエラーメッセージを追加した。
/demo/src/main/resources/ValidationMessages.properties
VMSG001=入力してください。
VMSG002={max}文字以下で入力してください。
VMSG003=選択してください。
3. Formクラス
AccountFormクラスの各フィールドに検証内容に応じたアノテーションを追加する。
/demo/src/main/java/com/ziqoo/demo/web/form/account/AccountForm.java
@NotBlank(message = "{VMSG001}")
@Size(max = 100, message = "{VMSG002}")
private String username;
@NotBlank(message = "{VMSG001}")
@Size(max = 100, message = "{VMSG002}")
private String password;
@NotEmpty(message = "{VMSG003}")
private List<Role> roleList;
4. Controllerクラス
ユーザ登録処理「register」メソッドを以下のように修正する。
/demo/src/main/java/com/ziqoo/demo/web/controller/account/AccountController.java
@Controller
public class AccountController {
private static final Logger logger = LoggerFactory.getLogger(AccountController.class);
@Autowired
private AccountService accountService;
@GetMapping("/account/register")
public String registrationPage(@ModelAttribute("accountForm") AccountForm form, Model model) {
model.addAttribute("roles", Role.values());
return "account/registration";
}
@PostMapping("/account/register")
public String register(@Validated AccountForm form, BindingResult bindingResult, Model model,
RedirectAttributes ra) {
if (bindingResult.hasErrors()) {
return registrationPage(form, model);
}
UserInfo user = accountService.registerAccount(form.getUsername(), form.getPassword(), form.getRoleList());
logger.debug("ユーザを登録しました。{}:{}", user.getId(), user.getUsername());
String message = user.getUsername() + "を登録しました。";
ra.addFlashAttribute("message", message);
return "redirect:/account/register";
}
}
5. エラーを個別に表示する場合
登録画面のhtmlを以下のように修正する。
/demo/src/main/resources/templates/account/registration.html
<table>
<tr>
<td><label for="username">ユーザ名</label></td>
<td>
<input type="text" th:field="*{username}" th:classappend="${#fields.hasErrors('username')} ? 'has-error'">
<span th:if="${#fields.hasErrors('username')}" th:errors="*{username}" style="color: red;"></span>
</td>
</tr>
<tr>
<td><label for="password">パスワード</label></td>
<td>
<input type="password" th:field="*{password}" th:classappend="${#fields.hasErrors('password')} ? 'has-error'">
<span th:if="${#fields.hasErrors('password')}" th:errors="*{password}" style="color: red;"></span>
</td>
</tr>
<tr>
<td><label>Role</label></td>
<td>
<div th:each="item : ${roles}" th:classappend="${#fields.hasErrors('roleList')} ? 'has-error'">
<input type="checkbox" th:value="${item}" th:field="*{roleList}" />
<label th:for="${#ids.prev('roleList')}" th:text="${item}"></label>
</div>
<span th:if="${#fields.hasErrors('roleList')}" th:errors="*{roleList}" style="color: red;"></span>
</td>
</tr>
</table>
6. エラーを一覧表示する場合
エラーを一覧表示する場合はどのフィールドのエラーかわかるように、フィールド名が表示されるようにする。
- そのために、エラーメッセージに{0}を追加する。
/demo/src/main/resources/ValidationMessages.properties
VMSG001={0}を入力してください。
VMSG002={0}は{max}文字以下で入力してください。
VMSG003={0}を選択してください。
- またこのままではフィールド名が「username」のようにそのまま表示されるので、日本語名で表示されるよう、messages.propertiesに以下を追加する。
/demo/src/main/resources/messages.properties
username=ユーザ名 password=パスワード roleList=Role
- 最後に登録画面のhtmlを以下のように修正する。
/demo/src/main/resources/templates/account/registration.html
<form th:action="@{/account/register}" th:object="${accountForm}" method="post">
<ul th:if="${#fields.hasErrors('*')}" style="color: red;">
<li th:each="err : ${#fields.errors()}" th:text="${err}"></li>
</ul>
<table>
<tr>
<td><label for="username">ユーザ名</label></td>
<td>
<input type="text" th:field="*{username}" th:classappend="${#fields.hasErrors('username')} ? 'has-error'">
</td>
</tr>
<tr>
<td><label for="password">パスワード</label></td>
<td>
<input type="password" th:field="*{password}" th:classappend="${#fields.hasErrors('password')} ? 'has-error'">
</td>
</tr>
<tr>
<td><label>Role</label></td>
<td>
<div th:each="item : ${roles}" th:classappend="${#fields.hasErrors('roleList')} ? 'has-error'">
<input type="checkbox" th:value="${item}" th:field="*{roleList}" />
<label th:for="${#ids.prev('roleList')}" th:text="${item}"></label>
</div>
</td>
</tr>
</table>

