두가지의 기능을 수행. 변환과 검증의 결과를 Binding Result에 저장한다.
양방향 타입 변환 (문자열->타입, 타입->문자열)
WebBindingInitializer 구현 후 등록
컨트롤러 내부에 @InitBinder 어노테이션이 붙은 메서드를 작성
@InitBinder
public void toDate(WebDataBinder binder){
SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd");
binder.registerCustomEditor(Date.class, new CustomDateEditor(df, false));
}
단방향 타입 변환 (타입A->타입B)
PropertyEditor는 인스턴스 변수를 이용하는 것 -> stateful하기 때문에 싱글톤으로 사용할 수 없음 (인스턴스가 생성될때마다 다시 에디터를 추가해줘야됨)
-->convert는 stateless
public class StringToStringArrayConverter implements Converter<String, String[]>{
@Override
public String[] convert(String source){ //string -> string 배열
return source.split("#");
}
}
타입 변환 서비스 제공. 여러 Converter를 등록할 수 있고 WebDataBinder에 DefaultFormattingConversionService가 기본적으로 등록되어 있다.
양방향 타입 변환 (문자열->타입, 타입->문자열)
바인딩할 필드에 적용 (ex. @NumberFormat
, @DateTimeFormat
)
@DateTimeFormat(pattern = "yyyy/MM/dd")
Date birth;
@NumberFormat(pattern = "###,###")
BigDecimal salary;
객체를 검증하기 위한 인터페이스. 객체 검증기 구현에 사용된다.
public class UserValidator implements Validator {
@Override
public boolean supports(Class<?> clazz) {
return User.class.isAssignableFrom(clazz); // clazz가 User나 User의 자손인지 확인
}
@Override
public void validate(Object target, Errors errors) {
System.out.println("LocalValidator.validate() is called");
// support 메서드를 통해 User로 캐스팅이 가능한 객체만 들어와있기 때문에
// instanceof를 사용하지 않아도 된다
User user = (User)target;
String id = user.getId();
// if(id==null || "".equals(id.trim())) {
// errors.rejectValue("id", "required"); //id필드에 에러코드로 required를 저장
// }
// 위와 동일
ValidationUtils.rejectIfEmptyOrWhitespace(errors, "id", "required");
ValidationUtils.rejectIfEmptyOrWhitespace(errors, "pwd", "required");
if(id==null || id.length() < 5 || id.length() > 12) {
errors.rejectValue("id", "invalidLength");
}
}
}
UserValidator userValidator = new UserValidator();
userValidator.validate(user, result);
if (result.hasErrors()) return "registerForm";
return "registerInfo";
@InitBinder
public void toDate(WebDataBinder binder){
...
//validator 등록
binder.setValidator(new UserValidator());
...
}
@PostMapping("/register/save")
//검증하려는 매개변수 앞에 @Valid 어노테이션
public String save(Model m, @Valid User user, BindingResult result){
if (result.hasErrors()) return "registerForm";
return "registerInfo";
}
하나의 Validator로 여러 객체를 검증하고자 할 때 이용
<annotation-driven validator="globalValidator"/>
<beans:bean id="globalValidator" class="com.fastcampus.ch2.GlobalValidator"/>
@InitBinder
public void toDate(WebDataBinder binder){
...
//꼭 addValidator 메서드를 이용해야됨!!
binder.addValidator(new UserValidator());
...
}