임도현의 성장
Spring-Boot Bean validationn 본문
Bean Validation 이란?
먼저 Bean Validation은 특정한 구현체가 아니라 Bean Validation 2.0(JSR-380)이라는 기술 표준이다.
쉽게 이야 기해서 검증 애노테이션과 여러 인터페이스의 모음이다.
Bean Validation을 잘 활용하면, 애노테이션 하나로 검증 로직을 매우 편리하게 적용할 수 있다.
1. validation 의존성 주입
- build.gradle 에 의존관계를 추가하면 라이브러리가 추가 된다
implementation 'org.springframework.boot:spring-boot-starter-validation'
2. 테스트 코드 작성
@Data
public class Item {
private Long id;
// @NotBlank 빈값 + 공백만 있는 경우를 허용하지 않는다.
@NotBlank(message = "이름은 필수 입력 값입니다.")
private String itemName;
@NotNull(message = "가격은 필수 입력 값입니다.") // null 을 허용하지 않는다
@Range(min = 1000, max = 1000000) // 범위 안의 값이어야 한다.
private Integer price;
@NotNull(message = "갯수는 필수 입력 값입니다.")
@Max(9999) // 최대 9999까지만 허용한다.
private Integer quantity;
public Item() {
}
public Item(String itemName, Integer price, Integer quantity) {
this.itemName = itemName;
this.price = price;
this.quantity = quantity;
}
}
3. Controller 적용해보기
@GetMapping("/items/add")
public String add(Model model){
model.addAttribute("item", new Item());
return "item/addForm";
}
@PostMapping("/items/add")
public String save(@Valid @ModelAttribute("item") Item item, BindingResult bindingResult, Model model, RedirectAttributes redirectAttributes){
log.info("objectName={}", bindingResult.getObjectName()); // @ModelAttribute name
log.info("target={}", bindingResult.getTarget()); // 검증해야할 객체
log.info("item={}", item);
if (bindingResult.hasErrors()) {
log.info("errors={}", bindingResult);
model.addAttribute("item", item);
return "item/addForm";
}
//성공 로직
Item savedItem = itemRepository.save(item);
redirectAttributes.addAttribute("itemId", savedItem.getId());
// 리다이렉트 status 속성 추가 URL에 쿼리 파라미터로 추가될 수 있습니다.
redirectAttributes.addAttribute("status", true);
return "redirect:/basic/items/{itemId}";
}
- @ModelAttribute는 요청 파라미터를 자동으로 객체 필드에 바인딩하고, 해당 객체를 모델에 추가하는 매우 편리한 어노테이션입니다
- @Valid 유형성 검증을 위한 어노테이션
- 순서가 중요 @ModelAttribute 앞에 @Valid가 있어야 합니다
- Item 상품을 등록할때 hasErrors() 메서드를 통해 Item객체에 설정한 유효성 검사에 문제가 있는지 확인하고 문제가 있을시 다신 이전 View로 보내주면 된
4. html 작성
<form th:action th:object="${item}" method="post">
<div>
<label for="itemName" >상품명</label>
<input type="text" id="itemName" name="itemName" th:field="*{itemName}" class="form-control" placeholder="이름을 입력하세요">
<div class="field-error" th:errors="*{itemName}">
상품명 오류
</div>
</div>
<div>
<label for="price">가격</label>
<input type="text" id="price" th:field="*{price}" class="form-control" placeholder="가격을 입력하세요">
<div class="field-error" th:errors="*{price}">
가격 오류
</div>
</div>
<div>
<label for="quantity">수량</label>
<input type="text" id="quantity" name="quantity" th:field="*{quantity}" class="form-control" placeholder="수량을 입력하세요">
<div class="field-error" th:errors="*{quantity}">
수량 오류
</div>
</div>
<hr class="my-4">
<div class="row">
<div class="col">
<button class="w-100 btn btn-primary btn-lg" type="submit">상품 등록</button>
</div>
<div class="col">
<button class="w-100 btn btn-secondary btn-lg"
th:onclick="|location.href='@{/basic/items}'|"
type="button">취소</button>
</div>
</div>
</form>
5. 실행


6. message.properties
- 위에 사진을 보면 상품을 아무것도 안적었을때는 message값이 출력이 되는데 왜 @Range 오류는 다른 메세지가 나타나는 걸까 ?
- log.info를 찍어보면 이름을 알려준다
log.info("errors={}", bindingResult);
codes [NotBlank.item.itemName,NotBlank.itemName,NotBlank.java.lang.String,NotBlank];
codes [Range.item.price,Range.price,Range.java.lang.Integer,Range];
- message.properties 에 1순위 코드 이름을 작성후 원하는 메세지를 담으면 된다
NotBlank.itemName=이름은 필수 입력 값입니다.
Range.item.price=가격은 {2} ~ {1} 까지 허용합니다.
참고 자료
스프링 MVC 2편 - 백엔드 웹 개발 활용 기술 참고
'Spring Boot' 카테고리의 다른 글
Spring-Boot @Transactional 트랜잭션 전파 (0) | 2024.09.15 |
---|---|
Spring-Boot H2 데이터베이스 설정과 연결 (1) | 2024.09.02 |
Spring-Boot MyBatis (0) | 2024.09.01 |
Spring-Boot Cookie Session (2) | 2024.08.13 |
Spring-Boot Interceptor (38) | 2024.07.26 |