感謝のプログラミング 10000時間

たどり着いた結果(さき)は、感謝でした。

Spring MVCでバリデーションを利用する

スポンサーリンク

1.イントロダクション

「バリデーション」とは「値のチェック」のこと。
Spring FrameworkではJSR-303 Bean Validation APIを利用する。

Bean Validation APIとは、Beanのバリデーションチェックを行うための機能のこと。
このバリデーションを設定しておくことで、フォームの値を自力でいちいちチェックしなくてもフレームワークが勝手にチェックしてくれるようになる。

2.準備

バリデーションに必要なライブラリを追加するために、pom.xmlに以下を追記する

・pom.xml

<!-- validation -->
<dependency>
	<groupId>javax.validation</groupId>
	<artifactId>validation-api</artifactId>
	<version>1.1.0.Final</version>
</dependency>
<dependency>
	<groupId>org.hibernate</groupId>
	<artifactId>hibernate-validator</artifactId>
	<version>5.0.1.Final</version>
</dependency>

追記してmaven installすれば勝手に依存関係は解決される。

3.View

formタグを変更する。
具体的には、以下を追加する。

<form:errors path="*" element="div" />

コード全体はこちら。
・person-regist.jsp

<!DOCTYPE html>

<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<%@ taglib prefix="form" uri="http://www.springframework.org/tags/form" %>
<html>
	<head>
		<meta charset="utf-8">
		<title>${title}</title>
	</head> 
	<body>
		<h2>${titleMessage}</h2>
		<table>
		<form:form modelAttribute="personForm" action="add">
			<tr><td><form:errors path="*" element="div" /></td></tr>
			<tr><td><form:label path="name">名前:</form:label></td>
			<td><form:input path="name" size="20"/></td>
			</tr>
			<tr><td><form:label path="height">身長:</form:label></td>
			<td><form:input path="height" size="6"/></td>
			</tr>
			<tr><td><input type="submit"></td></tr>
		</form:form>
		</table>
		
		<c:if test="${dataList != null}" >
		<table border="1">
		<tr><th>名前</th><th>年齢</th></tr>
		<c:forEach var="obj" items="${dataList}" varStatus="status">
			<tr>
			<td><c:out value="${obj.name }"/></td>
			<td><c:out value="${obj.height }"/></td>
			</tr>
		</c:forEach>
		</table>
		</c:if>
	</body>
</html>

4.Controller

package sample;

import java.util.ArrayList;
import java.util.List;

import javax.validation.Valid;

import model.PersonForm;

import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;

@Controller
public class PersonController {
	private List<PersonForm> personList = new ArrayList<PersonForm>();

	@RequestMapping(value = "/person", method = RequestMethod.GET)
	public String person(Model model) {
		model.addAttribute("title","バリデーション");
		model.addAttribute("titleMessage","バリデーションを使ってみよう");
		PersonForm personForm = new PersonForm();
		model.addAttribute("personForm", personForm);
		model.addAttribute("dataList", personList);
		
		return "person-regist";
	}
	
	@RequestMapping(value = "/add", method = RequestMethod.POST)
	public String form(@Valid @ModelAttribute PersonForm personForm, BindingResult result, Model model) {
		
		if (result.hasErrors()) {
			model.addAttribute("title", "[ERROR]");
			model.addAttribute("titleMessage", "値をチェックしてください");
		} else {
			personList.add(personForm);
			model.addAttribute("title","バリデーション");
			model.addAttribute("titleMessage", "バリデーションしてみた!");
			model.addAttribute("dataList", personList);
			model.addAttribute("personForm", new PersonForm());
		}

		
		return "person-regist";
	}
}

以下の、

@RequestMapping(value = "/add", method = RequestMethod.POST)
public String form(@Valid @ModelAttribute PersonForm personForm, BindingResult result, Model model) {

という部分がポイントで、
@Validというアノテーションを使うことで、バリデーションチェックを実行できる。

result.hasErrors()は、バリデーションエラーがあればtrue,なければfalseを返す。

5.Model

モデルのプロパティにアノテーションでバリデートを設定する。

・PersonForm.java

package model;

import java.util.Date;

import javax.validation.constraints.Max;
import javax.validation.constraints.Min;
import javax.validation.constraints.NotNull;

import org.hibernate.validator.constraints.NotEmpty;

public class PersonForm {
	
	@NotEmpty
	private String name;
	
	@NotNull
	@Min(0)
	@Max(300)
	private Integer height;
	
	private Date registerDate;
	
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public Integer getHeight() {
		return height;
	}
	public void setHeight(Integer height) {
		this.height = height;
	}
	public Date getRegisterDate() {
		return registerDate;
	}
	public void setRegisterDate(Date registerDate) {
		this.registerDate = registerDate;
	}

}

ここでプロパティに@NotEmptyとか、@Min,@Maxがついていることに注目。

@NotEmptyは値が空でないことを確認する。
フォームから空で送信されたものは、「空の文字列」となるため、@NotEmptyを使う。
@NotNullはnullでないことを確認する。

@Minは整数値の最小値、@Maxは整数の最大値を指定する。

公式ドキュメントは以下。
http://docs.spring.io/spring/docs/3.0.0.RC3/reference/html/ch05s07.html


なお、Integer型のプロパティに@NotEmptyを設定したら、以下のようなエラーが出た。

org.springframework.web.util.NestedServletException: Request processing failed; nested exception is javax.validation.UnexpectedTypeException: HV000030: No validator could be found for type: java.lang.Integer.

Integerには@NotNullを使うとよい。
参考)
http://stackoverflow.com/questions/5982741/error-no-validator-could-be-found-for-type-java-lang-integer

4.デモ

・初期画面
f:id:sho322:20140115201917j:plain
・異常な値を入力した場合
f:id:sho322:20140115201944j:plain
f:id:sho322:20140115201951j:plain

5.参考にした本

基礎的なことを省略せずに丁寧に解説してくれる素晴らしい本。
つまづかずに勉強することができている。