Goal
- 데이터 바인딩에 대해 알아본다
- PropertyEditor에 대해 알아본다
데이터 바인딩이란?
- 기술적인 관점 : 프로퍼값을 타겟 객체에 설정하는 기능
- 사용자 관점 : 사용자 입력값을 어플리케이션 도메인 모델에 동적으로 변환하여 넣어주는 기능
- org.springframework.validation.DataBinder
- 데이터 바인딩의 개념은 스프링 여러곳에서 쓰이는 핵심 기술 중 하나
즉, 입력값은 대부분 "문자열"인데 그 값을 객체가 가지고 다양한 타입(int, long, Boolean, Date 등 나아가 Event, Book)같은 도메인 타입으로도 변환하여 넣어주는 기능을 말한다.
DataBinder (Spring Framework 6.0.11 API)
Register the given custom property editor for the given type and property, or for all properties of the given type. If the property path denotes an array or Collection property, the editor will get applied either to the array/Collection itself (the Propert
docs.spring.io
public class DataBinder implements PropertyEditorRegistry, TypeConverter {
public interface PropertyEditorRegistry {
@Nullable
PropertyEditor findCustomEditor(@Nullable Class<?> requiredType, @Nullable String propertyPath);
}
public interface PropertyEditor {
=> 따라서 스프링은 바인딩의 기능을 여러 인터페이스로 추상화 시켜놓았다.
1. PropertyEditor Interface
- 스프링 3.0 이전까지 DataBinder가 변환 작업하던 인터페이스
- thread unsafe
- stateful - 상태 정보 저장 O
- 빈은 기본적으로 싱글톤 관리 되기 때문에, 빈으로 등록 금지 (상태 공유가 가능하기 때문에 멀티 쓰레드 환경에서 unsafe)
- 스레드 스콥의 빈으로 만들어야 함
- Object와 String간의 변환만 가능하여 사용 범위가 제한적
고전적인 방법의 데이터 바인딩 예
Event
public class Event {
Integer id;
String title;
public Event(Integer id) {
this.id = id;
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
@Override
public String toString() {
return "Event{" +
"id=" + id +
", title='" + title + '\'' +
'}';
}
}
EventEditor
public class EventEditor extends PropertyEditorSupport {
@Override
public String getAsText() {
Event event = (Event) getValue();
return event.getId().toString();
}
@Override
public void setAsText(String text) throws IllegalArgumentException {
setValue(new Event(Integer.parseInt(text)));
}
}
- PropertyEditorSupport를 상속받아 필요한 메소드를 구현
- 우리는 문자열 1로 들어오면 숫자 타입으로 변환 할 것임
- 빈 등록 금지
EventController
@RestController
public class EventController {
@InitBinder
public void init(WebDataBinder webDataBinder){
webDataBinder.registerCustomEditor(Event.class, new EventEditor());
}
@GetMapping("/event/{event}")
public String getEvent(@PathVariable Event event){
System.out.println(event);
return event.getId().toString();
}
}
- 빈으로 등록할 수 없기 때문에 @InitBinder를 사용하여 등록한다
EventControllerTest
@RunWith(SpringRunner.class)
@WebMvcTest
class EventControllerTest {
@Autowired
MockMvc mockMvc;
@Test
public void getTest() throws Exception {
mockMvc.perform(get("/event/1"))
.andExpect(status().isOk())
.andExpect(content().string("1"));
}
}
결과
Event{id=1, title='null'}
참고
스프링입문 강의 by 백기선
https://www.inflearn.com/course/lecture?courseSlug=spring&unitId=15538 https://www.inflearn.com/course/spring_revised_edition/dashboard
https://www.inflearn.com/course/spring_revised_edition/dashboard
'Spring > about spring' 카테고리의 다른 글
@Repository vs @Interface 그리고 Mybatis (1) | 2023.09.18 |
---|---|
[Resource / Validation] Validation 추상화 (0) | 2023.07.26 |
[Resource / Validation] Resource 추상화 (0) | 2023.07.25 |
[IoC 컨테이너와 빈] ResourceLoader (0) | 2023.07.24 |
[IoC 컨테이너와 빈] ApplicationEvent Publisher (0) | 2023.07.24 |