์ด๋ฒ ๊ธ์ ํตํด ์ด์ ๊ธ์์ BindingResult, FieldError, ObjectError๋ฅผ ํตํด ๋ง๋ค์ด๋ณด์๋ ๊ฒ์ฆ ๊ธฐ๋ฅ์ ์กฐ๊ธ ๋ ์ฝ๊ฒ ๋ง๋ค์ด๋ณด๊ณ ์ ํ๋ค.
1. rejectValue() & reject() ๐ฃ
FieldError์ ObjectError๋ ๋๋ฌด ๋ณต์กํ๋ค. BindingResult์ rejectValue์ reject๋ฅผ ์ฌ์ฉํ๋ฉด ์กฐ๊ธ ๋ ๊ฐ๊ฒฐํ๊ฒ ๊ฒ์ฆ์ ์งํํ ์ ์๋ค.
์ด์ ๊ธ์์ BindingResult๋ ํญ์ ๊ฒ์ฆํด์ผ ํ ๊ฐ์ฒด ๋ฐ๋ก ๋ค์ ์ด์ด์ ์์ฑํด์ผ ํ๋ค๊ณ ๋งํ ์ ์ด ์๋ค. ์ด๋ BindingResult๊ฐ ๊ฒ์ฆํด์ผ ํ ๊ฐ์ฒด๋ฅผ ์ด๋ฏธ ์๊ณ ์๋ ๊ฒ์ด๋ค. ์ด ์ ๋ณด๋ฅผ ๋ฐํ์ผ๋ก ์๋ ๋ด์ฉ๋ค์ ๊ณ์ํด์ ์ดํด๋ณด์.
rejectValue์ reject์ ์์ฑ์๋ ๋ค์๊ณผ ๊ฐ๋ค.
void rejectValue(@Nullable String field,
String errorCode,
@Nullable Object[] errorArgs,
@Nullable String defaultMessage);
void reject(String errorCode,
@Nullable Object[] errorArgs,
@Nullable String defaultMessage);
- field
์ค๋ฅ ํ๋๋ช - errorCode
์ค๋ฅ ์ฝ๋(์ด ์ค๋ฅ ์ฝ๋๋ ๋ฉ์์ง์ ๋ฑ๋ก๋ ์ฝ๋๊ฐ ์๋๋ค. ๋ค์์ ์ค๋ช ํ messageResolver๋ฅผ ์ํ ์ค๋ฅ ์ฝ๋์ด๋ค.) - errorArgs
์ค๋ฅ ๋ฉ์์ง์์ {0}์ ์นํํ๊ธฐ ์ํ ๊ฐ - defaultMessage
์ค๋ฅ ๋ฉ์์ง๋ฅผ ์ฐพ์ ์ ์์ ๋ ์ฌ์ฉํ๋ ๊ธฐ๋ณธ ๋ฉ์์ง
rejectValue()์ reject()๊ฐ ๋ด๋ถ์์ MessageCodesResolver๋ฅผ ์ฌ์ฉํ์ฌ ์ ์ ํ ์ค๋ฅ ๋ฉ์์ง๋ฅผ ์ ํ๊ฒ ๋๋ค.
2. messageCodesResolver ๐
messageCodesResolver๋ 'errorCode, ๊ฐ์ฒด ์ด๋ฆ, ํ๋ ์ด๋ฆ, ํ๋ ํ์ '์ ์ด์ฉํด์ ์ ์ ํ ์ค๋ฅ๋ฉ์์ง๋ฅผ ์ ํ๋ค. ์ค๋ฅ ๋ฉ์์ง๋ฅผ ์ฐพ์ ์ ์์ ๊ฒฝ์ฐ์๋ ์์์ ๋งํ ๊ฒ์ฒ๋ผ defaultMessage๋ฅผ ์ฌ์ฉํ๋ค.
MessageCodesResolve๋ ์ธํฐํ์ด์ค์ด๊ณ , DefaultMessageCodesResolver๋ ๊ธฐ๋ณธ ๊ตฌํ์ฒด์ด๋ค. DefaultMessageCodesResolver์ ๊ธฐ๋ณธ ๋ฉ์์ง ์์ฑ ๊ท์น์ ์๋์ ๊ฐ๋ค. ๊ฐ์ฒด ์ค๋ฅ๋ก ๋๋์ด์ ธ ์๊ณ ๋ฒํธ๊ฐ ๋ฎ์์๋ก ์ฐ์ ์์๊ฐ ๋๋ค.
๐ 1. ๊ฐ์ฒด ์ค๋ฅ
- errorCode + "." + object name
- code
errorCode๊ฐ required, object name์ด item์ด๋ฉด ์๋์ ๊ฐ์ ์ฐ์ ์์๋ฅผ ๊ฐ์ง๋ค.
- required.item
- required
๐ 2. ํ๋ ์ค๋ฅ
- errorCode + "." + object name + "." + field
- errorCode + "." + field
- errorCode + "." + field type
- errorCode
errorCode๊ฐ typeMismatch, object name์ด user, field๊ฐ age, field type์ด int๋ผ๋ฉด ์๋์ ๊ฐ์ ์ฐ์ ์์๋ฅผ ๊ฐ์ง๋ค.
- typeMismatch.user.age
- typeMismatch.age
- typeMismatch.int
- typeMismatch
MessageCodesResolver๋ฅผ ์ฌ์ฉํ๋ ์ด์ ๋ ๋ค์๊ณผ ๊ฐ๋ค๊ณ ํ ์ ์๋ค.
์ค๋ฅ ์ฝ๋๋ ์์ธํ ๋ง๋ค ์๋ ์๊ณ ๊ฐ๋จํ๊ฒ ๋ง๋ค ์๋ ์๋ค. ๋จ์ํ๊ฒ ๋ง๋ค๋ฉด ๋ฒ์ฉ์ฑ์ด ์ข์์ ์ฌ๋ฌ ๊ณณ์์ ์ฌ์ฉํ ์ ์์ง๋ง, ๋ฉ์์ง๋ฅผ ์ธ๋ฐํ๊ฒ ์์ฑํ๊ธฐ ์ด๋ ต๋ค๋ ๋ฌธ์ ๊ฐ ์๋ค. ๋ฐ๋ฉด์ ๋๋ฌด ์์ธํ๊ฒ ๋ง๋ค๋ฉด ๋ฒ์ฉ์ฑ์ด ๋จ์ด์ง๋ค.
๊ทธ๋ ๊ธฐ ๋๋ฌธ์ ์ธ๋ฐํ ๊ฒฝ์ฐ๊ฐ ํ์ํ๋ค๋ฉด ์์ธํ ๋ฉ์์ง๋ฅผ ๊ฐ์ ธ์ค๊ณ ๋ฒ์ฉ์ฑ์ด ์ค์ํ๋ค๋ฉด ๋จ์ํ ๋ฉ์์ง๋ฅผ ๊ฐ์ ธ์์ผ ํ๋ค.
3. ๊ตฌํ ๐ค
rejectValue์ reject๋ฅผ ์ฌ์ฉํ๋ฉด ์ด์ ์ FieldError์ ObjectError๋ก ๋ํ๋๋ ๊ฒ์ ๋ค์๊ณผ ๊ฐ์ด ๋ณ๊ฒฝํ ์ ์๋ค.
// ๊ธฐ์กด
bindingResult.addError(
new FieldError("item",
"itemName",
item.getItemName(),
false,
null,
null,
"์ํ ์ด๋ฆ์ ํ์์
๋๋ค."));
// ๋ณ๊ฒฝ
bindingResult.rejectValue("itemName", "required");
----------
// ๊ธฐ์กด
bindingResult.addError(new FieldError("item",
"price",
item.getPrice(),
false,
null,
null,
"๊ฐ๊ฒฉ์ 1,000 ~ 1,000,000 ๊น์ง ํ์ฉํฉ๋๋ค."));
// ๋ณ๊ฒฝ
bindingResult.rejectValue("price", "range", new Object[]{1_000, 1_000_000}, null);
----------
// ๊ธฐ์กด
bindingResult.addError(new FieldError("item",
"quantity",
item.getQuantity(),
false,
null,
null,
"์๋์ ์ต๋ 9,999 ๊น์ง ํ์ฉํฉ๋๋ค."));
// ๋ณ๊ฒฝ
bindingResult.rejectValue("quantity", "max", new Object[]{9_999}, null);
----------
// ๊ธฐ์กด
bindingResult.addError(new ObjectError("item",
null,
null,
"๊ฐ๊ฒฉ * ์๋์ ํฉ์ 10,000์ ์ด์์ด์ด์ผ ํฉ๋๋ค.. ํ์ฌ ๊ฐ = " + resultPrice));
// ๋ณ๊ฒฝ
bindingResult.reject("totalPriceMin", new Object[]{10_000, resultPrice}, null);
// application.properties
spring.messages.basename=messages, errors
// /resources/errors.properteis
required.item.itemName=์ํ ์ด๋ฆ์ ํ์์
๋๋ค.
range.item.price=๊ฐ๊ฒฉ์ {0} ~ {1} ๊น์ง ํ์ฉํฉ๋๋ค.
max.item.quantity=์๋์ ์ต๋ {0} ๊น์ง ํ์ฉํฉ๋๋ค.
totalPriceMin=๊ฐ๊ฒฉ * ์๋์ ํฉ์ {0}์ ์ด์์ด์ด์ผ ํฉ๋๋ค. ํ์ฌ ๊ฐ = {1}
์ ์ฒด ์ฝ๋๋ ๋ค์๊ณผ ๊ฐ๋ค.
@Slf4j
@Controller
@RequiredArgsConstructor
public class ValidationController2 {
private final ItemRepository itemRepository;
@PostMapping("/add")
public String addItem(@ModelAttribute Item item, BindingResult bindingResult, RedirectAttributes redirectAttributes) {
// 1. ์์ดํ
์ด๋ฆ(itemName)์ด ์๋ ๊ฒฝ์ฐ
if(!StringUtils.hasText(item.getItemName())){
bindingResult.rejectValue("itemName", "required");
}
// 2. ๊ฐ๊ฒฉ(itemPrice)์ ๋ฒ์๊ฐ 1,000 ~ 1,000,000์ด ์๋ ๊ฒฝ์ฐ
if(item.getPrice() == null || item.getPrice() < 1000 | item.getPrice() > 1_000_000){
bindingResult.rejectValue("price", "range", new Object[]{1_000, 1_000_000}, null);
}
// 3. ๊ฐ์(quantity)๊ฐ ์ต๋ 9,999๊ฐ๊ฐ ์๋ ๊ฒฝ์ฐ
if(item.getQuantity() == null || item.getQuantity() > 10_000) {
bindingResult.rejectValue("quantity", "max", new Object[]{9_999}, null);
}
// ํน์ ํ๋ ์์ธ๊ฐ ์๋ ์ ์ฒด ์์ธ
// 4. ์ต์ข
๊ฐ(๊ฐ๊ฒฉ(itemPrice) * ๊ฐ์(quantity))์ด 10,000์ ๋ฏธ๋ง์ธ ๊ฒฝ์ฐ
if(item.getPrice() != null && item.getQuantity() != null){
int resultPrice = item.getPrice() * item.getQuantity();
if(resultPrice < 10_000) {
bindingResult.reject("totalPriceMin", new Object[]{10_000, resultPrice}, null);
}
}
if(bindingResult.hasErrors()){
return "item/addForm"; // ๋ค์ ์ํ ๋ฑ๋กํ์ด์ง๋ก ์ด๋
}
Item savedItem = itemRepository.save(item);
redirectAttributes.addAttribute("itemId", savedItem.getId());
redirectAttributes.addAttribute("status", true);
return "redirect:/items/{itemId}";
}
}
ํด๋น ๊ธ์ ๊น์ํ ๋์ '์คํ๋ง MVC 2ํ - ๋ฐฑ์๋ ์น ๊ฐ๋ฐ ํ์ฉ ๊ธฐ์ '์ ์ฐธ๊ณ ํ์์ต๋๋ค.
'๐ ์คํ๋ง > ๊ธฐ๋ณธ ๊ฐ๋ ' ์นดํ ๊ณ ๋ฆฌ์ ๋ค๋ฅธ ๊ธ
[Spring] ๊ฒ์ฆ(Validation) - Validator (0) | 2023.05.02 |
---|---|
[Spring] ๊ฒ์ฆ(Validation) - BindingResult, FieldError, ObjectError (0) | 2023.05.01 |
์คํ๋ง ์ธํฐ์ ํฐ(Spring Interceptor) (0) | 2023.04.30 |
์๋ธ๋ฆฟ ํํฐ(Servlet Filter) (0) | 2023.04.29 |
๋ฉ์์ง & ๊ตญ์ ํ (Message & Internationalization) (0) | 2023.04.25 |