LocalDate
, ์ ์ ๋ String
๋ฑ์ผ๋ก ๋ณํํ ๋ ์ฌ์ฉ.@InitBinder
์ ํจ๊ป ํน์ ํ๋์๋ง ์ ์ฉ ๊ฐ๋ฅ.PropertyEditorSupport
์ getValue()
์ setValue()
๋ฉ์๋๋ thread-safe ํ์ง ์๋ค.โ๏ธ ์์ ํ๊ฒ ์ฌ์ฉํ๋ ค๋ฉด?
@InitBinder
.โ๏ธ ๊ฒฐ๋ก : PropertyEditor๋ ์์ฒญ ์ค์ฝํ ๋ด์์๋ง ์ฌ์ฉํด์ผ ์์ !
@InitBinder
๋ ์ปจํธ๋กค๋ฌ ๋จ์๋ก ๋์ํ๋ฉฐ, ์์ฒญ ์ ์์ฑ๋๋ WebDataBinder์ ์ปค์คํ
์๋ํฐ๋ฅผ ๋ฑ๋ก.PropertyEditorSupport
๋ ์์ ํ๊ฒ ์ฌ์ฉ ๊ฐ๋ฅ.โ๏ธ ์ ๋ฆฌ:
@InitBinder ์ฌ์ฉ ์ด์
1๏ธโฃ ์์ฒญ๋ง๋ค ์์ ํ๊ฒ ์ปค์คํ
์๋ํฐ ์ ์ฉ
2๏ธโฃ ๋ฐ๋ณต์ ์ธ ๋ฐ์ดํฐ ํฌ๋งทํ
์๋ํ
3๏ธโฃ ํ๋ ๋จ์ ์ธ๋ฐํ ๋ฐ์ดํฐ ๋ณํ
javax.validation ์ฃผ์ ์ ๋ ธํ ์ด์
- ์ซ์:
@Min
,@Max
,@Positive
,@Negative
- ๋ฌธ์์ด:
@NotBlank
,@Size
,@Pattern
- ๋ ์ง:
@Future
,@Past
,@DateTimeFormat
- ๊ธฐํ:
@AssertTrue
,@CreditCardNumber
@Controller
@Slf4j
public class UserController {
@InitBinder
public void dataBinder(WebDataBinder webDataBinder) {
// ์ ํ๋ฒํธ์ ์์ผ ํ๋์ ๋ํด ์ปค์คํ
์๋ํฐ ๋ฑ๋ก
webDataBinder.registerCustomEditor(String.class, "phone", new PhoneNumberEditor());
webDataBinder.registerCustomEditor(LocalDate.class, "birthday", new BirthdayEditor());
}
@GetMapping("/join")
public void join() {
log.info("GET /join...");
}
@PostMapping("/join")
public void join_post(@Valid UserDto dto, BindingResult bindingResult, Model model) {
log.info("POST /join..." + dto);
if (bindingResult.hasErrors()) {
for (FieldError error : bindingResult.getFieldErrors()) {
log.info("Error Field: " + error.getField() + " | Msg: " + error.getDefaultMessage());
model.addAttribute(error.getField(), error.getDefaultMessage());
}
}
}
// ์์ผ ๋ณํ์ฉ ์๋ํฐ
private static class BirthdayEditor extends PropertyEditorSupport {
@Override
public void setAsText(String text) {
LocalDate date = text.isEmpty() ? LocalDate.now()
: LocalDate.parse(text.replaceAll("~", "-"), DateTimeFormatter.ofPattern("yyyy-MM-dd"));
setValue(date);
}
}
// ์ ํ๋ฒํธ ํฌ๋งทํ
์๋ํฐ
private static class PhoneNumberEditor extends PropertyEditorSupport {
@Override
public void setAsText(String phone) {
if (phone.isEmpty()) {
setValue("");
} else {
String formatNumber = phone.replace("-", "");
setValue(formatNumber);
}
log.info("PhoneNumberEditor's setAsText invoke..." + phone);
}
}
}
<form action="${pageContext.request.contextPath}/join" method="post">
<h1>ํ์๊ฐ์
</h1>
...
<div>
<label>phone:</label><span>${phone}</span><br>
<input name="phone" placeholder="ex)010-0000-0000" />
</div>
<div>
<label>birthday:</label><span>${birthday}</span><br>
<input type="text" name="birthday" placeholder="ex)2025~01~01"/>
</div>
<div>
<input type="submit" value="ํ์๊ฐ์
" />
</div>
</form>
INFO : UserController - UserController's dataBinder ํธ์ถ
INFO : UserController - POST /join...UserDto(phone=01012345678, birthday=2025-04-24)
INFO : PhoneNumberEditor - PhoneNumberEditor's setAsText invoke...010-1234-5678