Gidhub BE Developer

Spring 프레임워크 핵심 기술 - Converter와 Formatter 1부

2019-09-03
goodGid

이 글의 코드 및 정보들은 강의를 들으며 정리한 내용을 토대로 작성하였습니다.

Converter

  • 제네릭 타입으로 Source / Target을 입력받는다.

  • 상태정보가 없다
    = Stateless
    = Thread Safe하다.
    Property Editor의 단점을 보완했다.

  • 그러므로 Bean으로 등록하여 사용해도 된다.

Converter

  • 생성한 Converter 사용법은 ConverterRegistry에 등록하여 사용하면된다.

  • = Config같은 파일에 등록하여 사용하면 된다.

  • 바로 아래 Config 부분을 참고하자.

public class EventConverter {

    public static class StringToEventConverter implements Converter<String, Event> {
        @Override
        public Event convert(String s) {
            return new Event(Integer.parseInt(s));
        }
    }

    public static class EventToStringConvert implements Converter<Event, String> {
        @Override
        public String convert(Event event) {
            return event.getId().toString();
        }
    }
}

Config

  • @Configuration를 빠뜨려서 TC가 자꾸 실패했었다.
@Configuration
public class WebConfig implements WebMvcConfigurer {
    @Override
    public void addFormatters(FormatterRegistry registry) {
        // 여기서 Converter를 등록하면 된다.
        registry.addConverter(new StringToEventConverter());
    }
}

Formatter

  • Formatter = PropertyEditor + Locale 정보 + Thread Safe

PropertyEditor와 공통점

  • String <-> Object 라는 특징은 PropertyEditor와 동일하다.

PropertyEditor와 차이점

  • Converter와 마찬가지로 Thread Safe하기 때문에 Bean으로 등록하여 사용해도 된다.

  • 여기서 Locale 정보와 MessageSource를 사용하여 원하는 언어로 변경할 수 있다.

public class EventFormatter implements Formatter<Event> {

    @Autowired
    private MessageSource messageSource; // Bean으로 등록하였기 때문에 다른 Bean 주입이 가능하다 !

    @Override
    public Event parse(String s, Locale locale) throws ParseException {
        return new Event(Integer.parseInt(s));
    }

    @Override
    public String print(Event event, Locale locale) {
        String afterString = messageSource.getMessage(event.getName(),locale);
        return afterString;
    }
}

Config

  • Formatter를 등록하여 사용하는 방법은 Converter와 동일하다.
@Configuration
public class WebConfig implements WebMvcConfigurer {
    @Override
    public void addFormatters(FormatterRegistry registry) {
    //    registry.addConverter(new StringToEventConverter());
       registry.addFormatter(new EventFormatter());
    }
}

PropertyEditor와 Converter 동시 존재

  • 만약 PropertyEditor와 Converter가 동시에 존재한다면 어떻게될까? 라는 궁금증이 발생했다.

  • 개발 환경은 아무런 세팅을 하지 않은 상태이다.

Converter Code

public static class StringToEventConverter implements Converter<String, Event> {
        @Override
        public Event convert(String s) {
            return new Event(Integer.parseInt(s));
        }
    }

@InitBinder Code

@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();
    }
}

Case 1. @InitBinder 존재 O

  • PropertyEditor와 Converter 2개가 다 있는 상황에서

  • 컨트롤러의 @InitBinder를 살려놓고 TC를 실행시키면

  • 순서는 다음과 같았다.

1. Converter를 등록하는 코드 실행 
2. @InitBinder 실행
3. EventEditor의 setAsText() 실행 
4. 컨트롤러로 이동

Case 2. @InitBinder 존재 X

  • 컨트롤러의 @InitBinder를 주석처리하고 TC를 실행시키면
1. Converter를 등록하는 코드 실행 
2. Converter 실행
3. 컨트롤러로 이동

정리

  • Converter를 등록하는 과정은 동일하다.

  • 어차피 이 부분은 Config를 등록하는 과정이기 때문에 동일하다고 생각된다.

  • 그 다음에 컨트롤러에
    @InitBinder가 존재하면 PropertyEditor
    @InitBinder가 존재하지 않으면 Converter가 동작하는 것을 확인할 수 있었다.

  • 끝으로 사실 정확한 이유는 모르겠다. 아는 분이 있다면 댓글 혹은 메일로 알려주시면 대단히 감사하겠습니다 !!!


참고


Comments

Content