데이터 바인딩 추상화 : PorpertyEditor

org.springframework.validation.DataBinder

기술적인 관점: 프로퍼티 값을 타겟 객체에 설정하는 기능
사용자 관점: 사용자 입력값을 애플리케이션 도메인 모델에 동적으로 변환해 넣어주는 기능.
해석하자면: 입력값은 대부분 "문자열"인데, 그 값을 객체가 가지고 있는 int, long, Boolean, Date 등 심지어 Event, Book 같은 도메인 타입으로도 변환해서 넣어주는 기능.

PropertyEditor

  • 스프링 3.0 이전까지 DataBinder가 변환 작업 사용하던 인터펭이스
  • 쓰레드-세이프 하지 않음 (상태 정보 저장 하고 있음, 따라서 싱글톤 빈으로 등록해서 쓰다가는...)
  • Object와 String 간의 변환만 할 수 있어, 사용 범위가 제한적 임.(그래도 그런 경우가 대부분이기 때문에 잘 사용해 왔음. 조심해서..)

1. 데이터 바인딩 오류

  • Event.java
public class Event {

    private Integer id;

    private 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 + '\'' +
                '}';
    }
}
  • EventController.java
@RestController
public class EventController {

    @GetMapping("/event/{event}")
    public String getEvent(@PathVariable Event event) {
        System.out.println(event);
        return event.getId().toString();
    }
}
  • EventControllerTest.java
@RunWith(SpringRunner.class)
@WebMvcTest
public class EventControllerTest {

    @Autowired
    MockMvc mockMvc;

    @Test
    public void getTest() throws Exception {
        mockMvc.perform(get("/event/1"))
                .andExpect(status().isOk())
                .andExpect(content().string("1"));

    }
}

Test 실행결과 Event 타입을 String 타입으로 변환하지 못해 오류 발생

2. PropertyEditor 사용하여 데이터 바인딩

  • EventEditor.java 구현
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)));
    }
}

주의 : PropertyEditor는 Thread safe 하지 않기 때문에 절대로 Bean으로 등록하여 사용하면 안된다.

  • EventController.java 수정
@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();
    }
}

Test 실행결과 통과 하며, 콘솔에 event 객체도 잘 출력됨.

좋은 웹페이지 즐겨찾기