본문 바로가기
백엔드/Spring(Boot)

스프링 Bean Validation

by 김어찐 2021. 9. 29.
728x90

컨트롤러

 

팁!

수정 form 이랑 생성 form이랑 다르게 Validation 체크를 해야한다!

@ModelAttribute에 값 지정하지 않으면 스프링에서 자동으로 이름변경한다음 model에 넣어주므로 체크!

package hello.itemservice.web.validation;

import hello.itemservice.domain.item.Item;
import hello.itemservice.domain.item.ItemRepository;
import hello.itemservice.domain.item.SaveCheck;
import hello.itemservice.domain.item.UpdateCheck;
import hello.itemservice.web.validation.form.ItemSaveForm;
import hello.itemservice.web.validation.form.ItemUpdateForm;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.validation.BindingResult;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.servlet.mvc.support.RedirectAttributes;

import java.util.List;


@Slf4j
@Controller
@RequestMapping("/validation/v4/items")
@RequiredArgsConstructor
public class ValidationItemControllerV4 {

    private final ItemRepository itemRepository;




    @PostMapping("/add")
    // ModelAttribute 다음에 BindingResult가 무조건 와야함
    // bindingResult modelAttribute에 에러가 있으면 bindingResult에 에러를 담아준다.
    // 400 에러 뜨지 않음
    // 자동으로 검증한다 @Validated
    public String addItem(@Validated @ModelAttribute("item") ItemSaveForm form, BindingResult bindingResult, RedirectAttributes redirectAttributes, Model model) {


        // 특정 필드가 아닌 복합 룰 검증
        if (form.getPrice() != null && form.getQuantity()!=null) {
            int resultPrice = form.getPrice() * form.getQuantity();
            if (resultPrice < 10000) {
                // 속성값이 없으면 ObjectError에 넣어준다.
                bindingResult.reject("totalPriceMin",new Object[]{10000,resultPrice},null);

            }
        }

        // 검증에 실패하면 다시 임력 폼으로
        // model에 자동으로 bindingResult 담김
        if (bindingResult.hasErrors()) {
            log.info("errors = {}", bindingResult);
            return "validation/v4/addForm";
        }
        Item item = new Item();
        item.setItemName(form.getItemName());
        item.setPrice(form.getPrice());
        item.setQuantity(form.getQuantity());
        // 성공 로직
        Item savedItem = itemRepository.save(item);
        redirectAttributes.addAttribute("itemId", savedItem.getId());
        redirectAttributes.addAttribute("status", true);
        return "redirect:/validation/v4/items/{itemId}";
    }



    @PostMapping("/{itemId}/edit")
    public String edit(@PathVariable Long itemId, @Validated @ModelAttribute("item") ItemUpdateForm form, BindingResult bindingResult) {
        // 특정 필드가 아닌 복합 룰 검증
        if (form.getPrice() != null && form.getQuantity()!=null) {
            int resultPrice = form.getPrice() * form.getQuantity();
            if (resultPrice < 10000) {
                // 속성값이 없으면 ObjectError에 넣어준다.
                bindingResult.reject("totalPriceMin",new Object[]{10000,resultPrice},null);

            }
        }

        // 검증에 실패하면 다시 임력 폼으로
        // model에 자동으로 bindingResult 담김
        if (bindingResult.hasErrors()) {
            log.info("errors = {}", bindingResult);
            return "validation/v4/editForm";
        }

        Item item = new Item();
        item.setItemName(form.getItemName());
        item.setPrice(form.getPrice());
        item.setQuantity(form.getQuantity());

        itemRepository.update(itemId, item);
        return "redirect:/validation/v4/items/{itemId}";
    }

}

 

Form

import hello.itemservice.domain.item.SaveCheck;
import lombok.Data;
import org.hibernate.validator.constraints.Range;

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

@Data
public class ItemSaveForm {

    // 빈값 + 공백만 있는 경우를 허용하지 않는다
    @NotBlank
    private String itemName;

    // null을 허용하지 않는다
    @NotNull
    @Range(min=1000,max = 1000000)
    private Integer price;

    @NotNull
    @Max(value = 9999)
    private Integer quantity;


}
728x90

'백엔드 > Spring(Boot)' 카테고리의 다른 글

스프링 서블릿 필터 - 요청 로그  (0) 2021.09.30
스프링 로그인(쿠키, 세션)  (0) 2021.09.30
스프링 API JSON 검증  (0) 2021.09.29
스프링 검증 Validation  (0) 2021.09.24
스프링 메시지, 국제화  (0) 2021.09.23