# 폼 검증(form validation)
---
## 라이브러리 등록
폼 검증을 위한 라이브러리를 등록하자.
**pom.xml**
```xml
...
<!-- Form 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.1.3.Final</version>
</dependency>
...
```
## 어노테이션 작성
대상 클래스의 필드에 검증할 어노테이션을 적어준다.
**Review.java**
```java
public class Review {
Integer id;
@NotEmpty
String text;
@NotNull
Integer bookId;
Integer userId;
...
}
```
## 폼 검증 수행
폼 검증은 `@Valid` 어노테이션을 앞에 붙여줌으로써 수행된다. `@Valid` 어노테이션을 실행했다면 다음 파라미터에 BindingResult 객체를 넣어주자. 해당 객체는 폼 검증의 결과에 대한 정보를 가지게 된다. 추가로 아래 코드에서 RedirectAttributes 객체를 사용하였는데, 이는 리다이렉트시 1회성(flash) 모델 객체를 만들어 준다.
**ReviewsController.java**
```java
@RequestMapping(value = "/reviews", method = RequestMethod.POST)
public String create(@Valid @ModelAttribute Review review, BindingResult result, RedirectAttributes flash) {
if (result.hasErrors()) {
List<FieldError> fieldErrors = result.getFieldErrors();
flash.addFlashAttribute("fieldErrors", fieldErrors);
flash.addFlashAttribute("review", review);
return "redirect:/books/" + review.getBookId();
}
reviewMapper.create(review);
return "redirect:/books/" + review.getBookId();
}
```
## 에러 출력
리다이렉트되는 메소드를 확인해보자.
**BooksController.java**
```java
@RequestMapping(value = "/books/{id}", method = RequestMethod.GET)
public String show(@PathVariable int id, Model model) {
Book book = bookMapper.getBook(id);
model.addAttribute("book", book);
// 등록된 리뷰들
List<Review> reviews = reviewMapper.getReviews(id);
model.addAttribute("reviews", reviews);
// 새로운 리뷰 등록
Review review = new Review();
review.setBookId(id);
model.addAttribute("review", review);
return "books/show";
}
```
다음으로 뷰 페이지 코드를 확인하자.
**views/books/show.jsp**
```jsp
<f:form modelAttribute="review" action="${ reviewsPath }" method="post">
<c:forEach var="error" items="${ fieldErrors }">
<div class="alert alert-warning">
<strong>${ error.getField() }</strong>: ${ error.getDefaultMessage() }
</div>
</c:forEach>
<f:textarea path="text" cssClass="form-control" rows="5" />
<f:hidden path="bookId" />
<f:hidden path="userId" />
<button class="btn btn-block btn-primary" type="submit">리뷰 등록</button>
</f:form>
```
아무 내용 없는 리뷰를 등록 시, 폼 검증을 통해 에러가 출력된다.
![Imgur](http://i.imgur.com/0deVlVo.png)