[Spring] 데이터 바인딩 - Converter & Formatter

Junseo Kim·2020년 1월 27일
0

Converter와 Formatter는 DataBinder가 아닌, ConversionService에 등록이된다.

Converter

PropertyEditor의 여러 단점(stateful, String <-> Object 관계의 변환만 가능 etc)들 보완하기 위해 나온 것이 Converter이다.

string <-> object 이외에도 타입 변환 가능
Stateless - 쓰레드 safe

Converter는 source와 target을 설정해줘야한다.
Converter<source, target>
source는 바꾸기 전 데이터 타입이고,
target은 바꿀 데이터 타입이다.

아래와 같이 Converter를 만들어 줄 수 있다.

스크린샷 2020-01-27 오후 9.47.35.png

converter같은경우는 stateless기 때문에 Bean으로 등록해서 사용해도 아무 문제 없다.

ConverterRegistry에 등록해서 사용하는데, config파일을 만들어서 converter를 등록해주면 된다.

// 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 + '\'' +
                '}';
    }

}
// WebConfig.java

@Configuration
public class WebConfig implements WebMvcConfigurer {

    @Override
    public void addFormatters(FormatterRegistry formatterRegistry) {
        formatterRegistry.addConverter(new EventConverter.StringToEventConverter());
    }

}
// EventController

@RestController
public class EventController {
    
    // event/1
    // event/2
    // 이런식으로 요청이 들어오면 입력한 숫자를 Event 타입으로 변환하여 스프링이 받는다
    @GetMapping("/event/{event}")
    public String getEvent(@PathVariable Event event){ // @PathVariable로 Event를 도메인으로 받음
        System.out.println(event);

        return event.getId().toString();
    }

}
// EventConverter

public class EventConverter {

    // String을 Event 타입으로
    public static class StringToEventConverter implements Converter<String, Event> {

        @Override
        public Event convert(String s) {
            return new Event(Integer.parseInt(s));
        }
    }

    // Event 타입을 String으로
    public static class EventToStringConverter implements Converter<Event, String> {

        @Override
        public String convert(Event event) {
            return event.getId().toString();
        }
    }
}

실행하면, WebConfig에 넣어준 Converter가 모든 Controller에 전부 동작을한다. 따라서 EventController가 만약 "event/1" 요청을 받으면 EventConverter를 통해 Event 타입으로 변환이 되어 Controller에서 Event타입으로 받을 수 있는 것이다.

기본적으로 Integer 타입 같은 경우는 기본적으로 등록되어 있는 Converter가 자동으로 변환해준다. 즉, 스프링에 기본적으로 등록되어 있지 않은 경우만 Converter를 만들어서 사용한다.

Formatter

웹 쪽에 특화되어 있다

Formatter는 처리할 타입 하나를 받고, 2개의 메서드를 구현해주어야한다.

스크린샷 2020-01-27 오후 10.12.58.png

스크린샷 2020-01-27 오후 10.16.07.png

Formatter도 stateless, 즉 쓰레드 safe하므로 Bean으로 등록해서 사용할 수도 있다. Bean으로 등록할 수 있으면, 다른 Bean을 주입 받을 수도 있다.

스크린샷 2020-01-27 오후 10.18.09.png

Converter와 비슷하게 WebConfig에서 Formatter 등록을 해줘야한다.

// WebConfig.java

@Configuration
public class WebConfig implements WebMvcConfigurer {

    @Override
    public void addFormatters(FormatterRegistry formatterRegistry) {
        formatterRegistry.addFormatter(new EventFormatter());
    }

}
// EventController

@RestController
public class EventController {
    
    // event/1
    // event/2
    // 이런식으로 요청이 들어오면 입력한 숫자를 Event 타입으로 변환하여 스프링이 받는다
    @GetMapping("/event/{event}")
    public String getEvent(@PathVariable Event event){ // @PathVariable로 Event를 도메인으로 받음
        System.out.println(event);

        return event.getId().toString();
    }

}
// EventFormatter.java

public class EventFormatter implements Formatter<Event> {


    // 문자를 받아서 객체로(Locale 정보를 기반으로)
    @Override
    public Event parse(String s, Locale locale) throws ParseException {
        return new Event(Integer.parseInt(s));
    }

    // 객체를 받아서 문자로(Locale 정보를 기반으로)
    @Override
    public String print(Event event, Locale locale) {
        return event.getId().toString();
    }
}

0개의 댓글