Converter와 Formatter는 DataBinder가 아닌, ConversionService에 등록이된다.
PropertyEditor의 여러 단점(stateful, String <-> Object 관계의 변환만 가능 etc)들 보완하기 위해 나온 것이 Converter이다.
string <-> object 이외에도 타입 변환 가능
Stateless - 쓰레드 safe
Converter는 source와 target을 설정해줘야한다.
Converter<source, target>
source는 바꾸기 전 데이터 타입이고,
target은 바꿀 데이터 타입이다.
아래와 같이 Converter를 만들어 줄 수 있다.
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는 처리할 타입 하나를 받고, 2개의 메서드를 구현해주어야한다.
Formatter도 stateless, 즉 쓰레드 safe하므로 Bean으로 등록해서 사용할 수도 있다. Bean으로 등록할 수 있으면, 다른 Bean을 주입 받을 수도 있다.
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();
}
}