일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | ||||
4 | 5 | 6 | 7 | 8 | 9 | 10 |
11 | 12 | 13 | 14 | 15 | 16 | 17 |
18 | 19 | 20 | 21 | 22 | 23 | 24 |
25 | 26 | 27 | 28 | 29 | 30 | 31 |
- 구글 보안 api 활용
- abap value in field Data Class error
- spring MVC
- filter vs interceptor
- optional
- .orelseThrow
- 401오류
- jpa
- SpringMVC
- Testcode
- java.lang.AssertionError
- 쿠키의 정의
- 세션의 정의
- 유연한 컨트롤러1 - v5
- 세션vs쿠키
- spring
- MVC
- 인터셉터의 정의
- springSecurityFilterChain 오류
- Validation
- application-properties
- 쿠키란
- 필터의 정의
- 세션이란
- 김영한
- controller
- n+1
- @Controller
- BindingResult
- 필터vs인터셉터
- Today
- Total
ABAP DUMP ERROR 24시
BindingResult를 활용한 Validation 처리 [전 vs 후(version1,2) ] 본문
BindingResult를 활용한 Validation 처리 [전 vs 후(version1,2) ]
이운형 2022. 2. 19. 21:41# 인프런 김영한의 스프링 MVC 1편 - 백엔드 웹 개발 핵심 기술을 개인적으로 정리한 글입니다.
정리
Q. 과거 Validation 처리는 어떻게 했어?
Post방식으로 Error validation을 처리할때
1.Map<String, String> 형식으로 HashMap을 만든다
2.errors.put을 통해 errors들을 모은다
3.model.addAttribute(errors", errors)를 통해 model에 넘긴다.
4. 에러 메세지를 thymeleaf를 통해 내보낸다.
@PostMapping("/add")
public String addItem(@ModelAttribute Item item, RedirectAttributes redirectAttributes, Model model) {
// 타입 검증
// 가격, 수량에 문자가 들어가면 검증 오류 처리
// 필드 검증
// 상품명: 필수, 공백X
// 가격: 1000원 이상, 1백만원 이하
// 수량: 최대 9999
// 특정 필드의 범위를 넘어서는 검증
// 가격 * 수량의 합은 10,000원 이상
//검증 오류 결과를 보관
Map<String, String> errors = new HashMap<>();
//검증 로직
if (!StringUtils.hasText(item.getItemName())){
errors.put("itemName", "상품 이름은 필수입니다.");
}
if (item.getPrice() == null || item.getPrice() < 1000 || item.getPrice()>1000000){
errors.put("price", "가격은 1,000 ~ 1,000,000 까지 허용합니다.");
}
if(item.getQuantity()== null || item.getQuantity() >= 9999){
errors.put("quantity", "수량은 최대 9,999까지 허용합니다.");
}
if(item.getPrice() != null && item.getQuantity() != null){
int resultPrice = item.getPrice() * item.getQuantity();
if(resultPrice < 10000){
errors.put("globalError" , "가격 * 수량의 합은 10,000원 이상이어야 합니다. 현재 값 =" + resultPrice);
}
}
//검증에 실패하면 다시 입력 폼으로 가자.
if(!errors.isEmpty()){
log.info("errors = {}", errors);
model.addAttribute("errors", errors);
return "validation/v1/addForm";
}
<thymeleaf를 활용하여 조건식을 개발>
Error 시 오류 메세지를 날리는 방식으로 설계되었다.
<input type="text" id="itemName" th:field="*{itemName}"
th:class="${errors?.containsKey('itemName')} ? 'form-control field-error' : 'form-control'"
class="form-control" placeholder="이름을 입력하세요">
<div class="field-error" th:if="${errors?.containsKey('itemName')}"
th:text="${errors['itemName']}">
Q. 현재 Validation 처리는 어떻게 했어?
다음과 같이 BindingResult를 추가해!
@ModelAttribute 뒤에 꼭 BindingResult가 와야한다. 순서가 변경되면 오류가 난다.
@PostMapping("/add")
public String addItem(@ModelAttribute Item item, BindingResult bindingResult, RedirectAttributes redirectAttributes, Model model) {
@PostMapping("/add")
public String addItem(@ModelAttribute Item item, BindingResult bindingResult, RedirectAttributes redirectAttributes, Model model) {
//검증 로직
if (!StringUtils.hasText(item.getItemName())){
bindingResult.addError(new FieldError("item", "itemName", "상품 이름은 필수 입니다."));
}
if (item.getPrice() == null || item.getPrice() < 1000 || item.getPrice()>1000000){
bindingResult.addError(new FieldError("item", "price","가격은 1,000~ 1,000,000 까지 허용합니다." ));
}
if(item.getQuantity()== null || item.getQuantity() >= 9999){
bindingResult.addError(new FieldError("item", "quantity", "수량은 최대 9,999까지 허용됩니다."));
}
if(item.getPrice() != null && item.getQuantity() != null){
int resultPrice = item.getPrice() * item.getQuantity();
if(resultPrice < 10000){
bindingResult.addError(new ObjectError("item", "가격 * 수량의 합은 10,000원 이상이어야 합니다. 현재 값 = " + resultPrice));
}
}
//검증에 실패하면 다시 입력 폼으로 가자.
if(bindingResult.hasErrors()){
log.info("errors= {}", bindingResult);
return "validation/v2/addForm";
}
Item savedItem = itemRepository.save(item);
redirectAttributes.addAttribute("itemId", savedItem.getId());
redirectAttributes.addAttribute("status", true);
return "redirect:/validation/v1/items/{itemId}";
- bindingResult.addError(new FieldError())
- bindingResult.addError(new ObjectError())
그리고 bindinResult.hasErrors() 하면 validation/v2/addForm을 다시 보여주도록 설계하면 된다.
/** 추가내용 2022-02-20 **/
public String addItemV2(@ModelAttribute Item item, BindingResult bindingResult, RedirectAttributes redirectAttributes){
if(!StringUtils.hasText(item.getItemName())){
bindingResult.addError(new FieldError("item", "itemName", item.getItemName(),
false, null, null, "상품 이름은 필수입니다."));
}
if(item.getPrice() == null || item.getPrice()<1000 || item.getPrice()> 1000000){
bindingResult.addError(new FieldError("item", "price", item.getPrice(),
false, null, null, "가격은 1,000~ 1,000,000 까지 허용합니다."));
}
if (item.getQuantity() == null || item.getQuantity() > 10000){
bindingResult.addError(new FieldError("item", "quantity", "item.getQuantity", false, null, null , "수량은 최대 9,999까지 허용합니다."));
}
if (item.getPrice() != null && item.getQuantity() != null){
int resultPrice = item.getPrice() * item.getQuantity();
if (resultPrice < 10000){
bindingResult.addError(new ObjectError("item", null,null,"가격 + 수량의 합은 10,000원 이상이어야 합니다. 현재값 = " + resultPrice));
}
}
bindingResult 에는 다음과 같은 추가 기능이 존재한다.
bindingResult.addError(new FieldError(String objectName, String field, @Nullable Object rejectedValue, boolean bindingFailure, @Nullable String[] codes, @Nullable Object[] arguments, @Nullable String defaultMessage))
여기서 눈여겨야 봐야할 점은 @Nullable Object rejectedValue, boolean bindingFailure 이다 .
rejectedValue 가 바로 오류 발생시 사용자 입력 값을 저장하는 필드
bindingFailure : 타입 오류 같은 바인딩 실패인지, 검증 실패인지 구분 값
따라서
new FieldError("item", "price", item.getPrice(), false, null, null, "가격은 1,000 ~ 1,000,000 까지 허용합니다.")
처럼 파라미터를 넣어주면 오류 발생시에도 데이터가 날아가지 않고 남아있다.
'[WEB]Back-end > Spring MVC' 카테고리의 다른 글
BindingResult , add FieldError=-> rejectValue 변환 (0) | 2022.02.21 |
---|---|
BindingResult Version3 properties를 활용한 동적 변경 (0) | 2022.02.20 |
Thylmleaf 간단 용어 정리 (0) | 2022.02.18 |
HTTP 메시지 컨버터가 뭐야? (0) | 2022.02.16 |
스프링 서버에서 요청 데이터 만들기 (0) | 2022.02.16 |