springboot_validation : bean validation - groups

This commit is contained in:
haerong22
2021-07-17 20:12:53 +09:00
parent c5da0f0fe8
commit bcda7b7558
5 changed files with 89 additions and 12 deletions

View File

@@ -12,17 +12,18 @@ import javax.validation.constraints.NotNull;
//@ScriptAssert(lang = "javascript", script = "_this.price * _this.quantity >= 10000", message = "총 합은 10000원 이상 이다.")
public class Item {
@NotNull(groups = UpdateCheck.class) // 수정 시 요구사항 추가
private Long id;
@NotBlank
@NotBlank(groups = {SaveCheck.class, UpdateCheck.class})
private String itemName;
@NotNull
@Range(min = 1000, max = 1000000)
@NotNull(groups = {SaveCheck.class, UpdateCheck.class})
@Range(min = 1000, max = 1000000, groups = {SaveCheck.class, UpdateCheck.class})
private Integer price;
@NotNull
@Max(9999)
@NotNull(groups = {SaveCheck.class, UpdateCheck.class})
@Max(value = 9999, groups = {SaveCheck.class})
private Integer quantity;
public Item() {

View File

@@ -0,0 +1,4 @@
package hello.itemservice.domain.item;
public interface SaveCheck {
}

View File

@@ -0,0 +1,4 @@
package hello.itemservice.domain.item;
public interface UpdateCheck {
}

View File

@@ -2,6 +2,8 @@ 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 lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
@@ -40,7 +42,7 @@ public class ValidationItemControllerV3 {
return "validation/v3/addForm";
}
@PostMapping("/add")
// @PostMapping("/add")
public String addItem(@Validated @ModelAttribute Item item, BindingResult bindingResult, RedirectAttributes redirectAttributes, Model model) {
if (item.getPrice() != null && item.getQuantity() != null ) {
@@ -62,6 +64,27 @@ public class ValidationItemControllerV3 {
return "redirect:/validation/v3/items/{itemId}";
}
@PostMapping("/add")
public String addItem2(@Validated(SaveCheck.class) @ModelAttribute Item item, BindingResult bindingResult, RedirectAttributes redirectAttributes) {
if (item.getPrice() != null && item.getQuantity() != null ) {
int resultPrice = item.getPrice() * item.getQuantity();
if (resultPrice < 10000) {
bindingResult.reject("totalPriceMin", new Object[]{10000, resultPrice}, null);
}
}
// 검증 실패시
if (bindingResult.hasErrors()) {
return "validation/v3/addForm";
}
// 검증 성공시
Item savedItem = itemRepository.save(item);
redirectAttributes.addAttribute("itemId", savedItem.getId());
redirectAttributes.addAttribute("status", true);
return "redirect:/validation/v3/items/{itemId}";
}
@GetMapping("/{itemId}/edit")
public String editForm(@PathVariable Long itemId, Model model) {
@@ -70,11 +93,38 @@ public class ValidationItemControllerV3 {
return "validation/v3/editForm";
}
@PostMapping("/{itemId}/edit")
public String edit(@PathVariable Long itemId, @ModelAttribute Item item) {
// @PostMapping("/{itemId}/edit")
public String edit(@PathVariable Long itemId,
@Validated @ModelAttribute Item item, BindingResult bindingResult) {
if (item.getPrice() != null && item.getQuantity() != null ) {
int resultPrice = item.getPrice() * item.getQuantity();
if (resultPrice < 10000) {
bindingResult.reject("totalPriceMin", new Object[]{10000, resultPrice}, null);
}
}
if (bindingResult.hasErrors()) {
return "validation/v3/editForm";
}
itemRepository.update(itemId, item);
return "redirect:/validation/v3/items/{itemId}";
}
@PostMapping("/{itemId}/edit")
public String edit2(@PathVariable Long itemId,
@Validated(UpdateCheck.class) @ModelAttribute Item item, BindingResult bindingResult) {
if (item.getPrice() != null && item.getQuantity() != null ) {
int resultPrice = item.getPrice() * item.getQuantity();
if (resultPrice < 10000) {
bindingResult.reject("totalPriceMin", new Object[]{10000, resultPrice}, null);
}
}
if (bindingResult.hasErrors()) {
return "validation/v3/editForm";
}
itemRepository.update(itemId, item);
return "redirect:/validation/v3/items/{itemId}";
}
}

View File

@@ -8,6 +8,10 @@
.container {
max-width: 560px;
}
.field-error {
border-color: #dc3545;
color: #dc3545;
}
</style>
</head>
<body>
@@ -19,28 +23,42 @@
</div>
<form action="item.html" th:action th:object="${item}" method="post">
<div th:if="${#fields.hasGlobalErrors()}">
<p class="field-error" th:each="err : ${#fields.globalErrors()}" th:text="${err}">글로벌 오류 메시지</p>
</div>
<div>
<label for="id" th:text="#{label.item.id}">상품 ID</label>
<input type="text" id="id" th:field="*{id}" class="form-control" readonly>
</div>
<div>
<label for="itemName" th:text="#{label.item.itemName}">상품명</label>
<input type="text" id="itemName" th:field="*{itemName}" class="form-control">
<input type="text" id="itemName" th:field="*{itemName}" th:errorclass="field-error" class="form-control">
<div class="field-error" th:errors="*{itemName}">
상품명 오류
</div>
</div>
<div>
<label for="price" th:text="#{label.item.price}">가격</label>
<input type="text" id="price" th:field="*{price}" class="form-control">
<input type="text" id="price" th:field="*{price}" th:errorclass="field-error" class="form-control">
<div class="field-error" th:errors="*{price}">
가격 오류
</div>
</div>
<div>
<label for="quantity" th:text="#{label.item.quantity}">수량</label>
<input type="text" id="quantity" th:field="*{quantity}" class="form-control">
<input type="text" id="quantity" th:field="*{quantity}" th:errorclass="field-error" class="form-control">
<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" th:text="#{button.save}">저장</button>
<button class="w-100 btn btn-primary btn-lg" type="submit" th:text="#{button.save}">수정</button>
</div>
<div class="col">
<button class="w-100 btn btn-secondary btn-lg"