📝 데이터 바인딩 : 사용자가 입력한 문자열 값을 프로퍼티 타입에 맞춰 변환하여 할당하는 것
1. PropertyEditor ( 양뱡향 타입변환 / 스프링 3.0 이전 사용 )
🚨 PropertyEditor의 구현체는 빈으로 등록해서 사용하지 않는다.
- 쓰레드-세이프 하지 않음(상태 정보 저장 하고 있음)
- Object와 String간의 변환만 할 수 있어, 사용 범위가 제한적 임
특정 컨트롤러 내에서의 변환
User.java
private Date birth; ## Date 타입
private String[] hobby; ## String[ ] 타입
Controller
@GetMapping("/user/{type}")
public String save( @PathVariable User user , Model m ){
// 바인딩 되야할 객체 바로 뒤에 써야 하며,
// 컨트롤러에게 바인딩 결과를 주고 어떻게 처리할지 결정하게 한다.
}
@InitBinder
public void toDate( WebDataBinder binder ){
SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd");
binder.registerCustomEditor(Date.class , new CustomDateEditor(df, false) );
// =============================================================================
binder.registerCustomEditor(String[].class , new StringArrayPropertyEditor("#") );
binder.registerCustomEditor(String[].class , "hobby" , new StringArrayPropertyEditor("#") ); //hobby에만
// =============================================================================
view 입력 >>> 테니스#수영#탁구 / 받기를 원하는 형태 [ 테니스 , 수영 , 탁구 ]
결과 >>> [ 테니스#수영#탁구 ] 이렇게 하나의 문자열로 들어오지만
WebDataBinder 로 해결할 수있다. [ 테니스, 수영, 탁구 ]
}
2. Formatter ( 양방향 타입변환 ) String -> 타입 / 타입 -> String
바인딩할 필드에 적용 : @NumberFormat / @DateTimeFormat
사용 방법은 Convertet와 동일하다.
📝 Formatter의 특징
- PropertyEditor 대체
- Object - String 간 변환을 담당하는 web 특화 인터페이스
- Spring이 제공하는 ConversionService 인터페이스를 통해 사용됨
- 값(상태 정보)을 저장하지 않으므로 thread-safe함
- 빈으로 등록해서 사용할 수 있음
- 문자열을 Locale에 따라 다국화 처리 하는 기능 제공 (Optional)
## InitBinder 대신 사용할수 있는 어노테이션
@DateTimeFormat(pattern="yyyy-MM-dd")
private Date birth;
@NumberFormat(pattern="###,###")
private BigDecimal salary;
Formatter는 제네릭으로 한 개의 인자만을 받는다.
왜냐하면 Object와 String간의 변환을 담당하기 때문에 다른 하나의 인자는 String으로 정해져 있기 때문이다.
public class EventFormatter implements Formatter<Event> {
@Override
public Event parse(String text, Locale locale) throws ParseException {
return new Event(Integer.parseInt(text));
}
@Override
public String print(Event object, Locale locale) {
return object.getId().toString();
}
}
Converter와 마찬가지로 WebMvcConfigurer 인터페이스를 구현한 클래스에 Formatter를 등록할 수 있다.
@Configuration
public class WebConfig implements WebMvcConfigurer {
@Override
public void addFormatters(FormatterRegistry registry) {
registry.addFormatter(new EventFormatter());
}
}
3. Converter ( 단방향 타입변환 ) 타입A => 타입B
public class EventConverter {
public class StringToStringArrayConverter implements Converter<String , String[]>{
public String[] convert (String source) {
return source.split("#"); // String => String[]
}
}
public static class StringToEventConverter implements Converter<String, Event> {
public Event convert(String source){
return new Event(Integer.parseInt(source));
}
}
public static class EventToStringConverter implements Converter<Event, String>{
public String convert(Event source){
return source.getId().toString();
}
}
}
📝 Converter의 특징
- Spring3 부터 추가됨
- Spring이 제공하는 ConversionService 인터페이스를 통해 사용됨
- 값(상태 정보)을 저장하지 않으므로 thread-safe함
- 빈으로 등록해서 사용할 수 있음
1.Spring Web MVC만 사용하는 경우 - Web config에 등록 ( @Configuration )
위에서 작성한 Converter를 등록하려면 스프링MVC에서는 WebMvcConfigurer 인터페이스를 구현한 클래스를
작성해야 한다. WebMvcConfigurer 인터페이스의 addFormatters 메서드를 오버라이딩하여 Converter를 등록할 수 있다.
레지스트리에 등록한 Converter는 모든 Controller에 대해 동작하게 된다.
@Configuration
public class WebConfig implements WebMvcConfigurer {
@Override
public void addFormatters(FormatterRegistry registry) {
registry.addConverter(new EventConverter.StringToEventConverter());
}
}
2. Spring Boot를 사용하는 경우 - Converter를 빈으로 등록( @Component )
public class EventConverter {
@Component
// Converter<Source, Target>
public static class StringToEventConverter implements Converter<String, Event> {
public Event convert(String s) {
return new Event(Integer.parseInt(s));
}
}
@Component
public static class EventToStringConverter implements Converter<Event, String> {
public String convert(Event event) {
return event.getId().toString();
}
}
}