개발강의정리/Spring

[스프링 프레임워크 핵심 기술] 4-2. 데이터 바인딩 추상화-Converter와 Formatter

nineDeveloper 2019. 10. 6.
728x90

스프링 프레임워크 핵심 기술

포스팅 참조 정보

GitHub

공부한 내용은 GitHub에 공부용 Organizations에 정리 하고 있습니다

해당 포스팅에 대한 내용의 GitHub 주소

실습 내용이나 자세한 소스코드는 GitHub에 있습니다
포스팅 내용은 간략하게 추린 핵심 내용만 포스팅되어 있습니다

https://github.com/freespringlecture/spring-core-tech/tree/chap04-02-converter_formatter

 

freespringlecture/spring-core-tech

백기선님의 스프링 프레임워크 핵심 기술 강의 내용 정리. Contribute to freespringlecture/spring-core-tech development by creating an account on GitHub.

github.com

해당 포스팅 참고 인프런 강의

https://www.inflearn.com/course/spring-framework_core/dashboard

 

스프링 프레임워크 핵심 기술 - 인프런

이번 강좌는 스프링 부트를 사용하며 스프링 핵심 기술을 학습합니다 따라서 스프링 부트 기반의 프로젝트를 사용하고 있는 개발자 또는 학생에게 유용한 스프링 강좌입니다. 초급 웹 개발 Java Spring 온라인 강의

www.inflearn.com

실습 환경

  • Java Version: Java 11
  • SpringBoot Version: 2.1.2.RELEASE

4-2. 데이터 바인딩 추상화: Converter와 Formatter

스프링이 기본적으로 자동으로 Converting 해주지 않는 것만 만들면 됨
추천은 Formatter를 사용하는 것을 추천함

Converter

https://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/core/convert/converter/Converter.html

 

Converter (Spring Framework 5.2.0.RELEASE API)

A converter converts a source object of type S to a target of type T. Implementations of this interface are thread-safe and can be shared. Implementations may additionally implement ConditionalConverter.

docs.spring.io

PropertyEditor 대신에 사용할 수 있는 기능 중에 하나
상태 정보가 없으므로 얼마 든지 빈으로 등록해서 사용해도 상관은 없음

  • S타입을 T타입으로 변환할 수 있는 매우 일반적인 변환기

  • 상태 정보 없음 == Stateless == 쓰레드세이프

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

ConverterResistry

https://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/core/convert/converter/ConverterRegistry.html

 

ConverterRegistry (Spring Framework 5.2.0.RELEASE API)

Add a plain converter to this registry. The convertible source/target type pair is specified explicitly. Allows for a Converter to be reused for multiple distinct pairs without having to create a Converter class for each pair.

docs.spring.io

ConverterRegistry​에 등록해서 사용
아래와 같이 설정하면 스프링MVC설정에 넣어준 Converter가 모든 컨트롤러에서 동작함

@Configuration
public class WebConfig implements WebMvcConfigurer {

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

Formatter

https://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/format/Formatter.html

 

Formatter (Spring Framework 5.2.0.RELEASE API)

 

docs.spring.io

  • PropertyEditor 대체제

  • Object와 String 간의 변환을 담당한다

  • 문자열을 Locale에 따라 다국화하는 기능도 제공한다 (optional)

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

FormatterRegistry

 

FormatterRegistry (Spring Framework 5.2.0.RELEASE API)

Adds a Formatter to format fields of the given type. On print, if the Formatter's type T is declared and fieldType is not assignable to T, a coercion to T will be attempted before delegating to formatter to print a field value. On parse, if the parsed obje

docs.spring.io

ConversionService

DataBinder대신에 Converter와 Formatter을 활용할 수 있게 해줌
인터페이스를 통해서 등록되는 Converter와 Formatter들은 ConversionService에 등록이 되고
ConversionService를 통해서 실제 변환하는 작업을 함

  • 실제 변환 작업은 이 인터페이스를 통해서 쓰레드-세이프하게 사용할 수 있음
  • 스프링 MVC​​, 빈 (value) 설정, SpEL에서 사용한다
  • DefaultFormattingConversionService

    자주 사용하게 되는 클래스

    • FormatterRegistry
    • ConversionService
    • 여러 기본 Converter와 Formatter를 등록 해줌

04-02.png

스프링 부트

  • 웹 애플리케이션인 경우에 DefaultFormattingConversionSerivce를 상속하여 만든
    WebConversionService​​를 빈으로 등록해 준다(더 많은 기능들이 포함)
  • Formatter와 Converter 빈을 찾아 자동으로 등록해 준다

Converter

빈으로 등록하면 WebConversionService​​가 빈을 찾아 자동으로 등록

public class EventConverter {

    @Component
    public static class StringToEventConverter implements Converter<String, Event> {

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

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

Formatter

빈으로 등록하면 WebConversionService​​가 빈을 찾아 자동으로 등록

@Component
public class EventFormatter implements Formatter<Event> {
    @Override
    public Event parse(String text, Locale locale) throws ParseException {
        return new Event(Integer.parseInt(text));
    }

    @Override
    public String print(Event object, Locale locale) {
        return object.getId().toString();
    }
}

테스트

@WebMvcTest는 슬라이싱 테스트
웹과 관련된 빈만 등록해주는 계층형 테스트라서 컨트롤러들만 주로 등록이 됨
Formatter나 Converter가 빈으로 등록이 안되면 테스트가 깨질 우려가 있음
@WebMvcTest 안에 등록해주면 빈으로 등록이 됨
그냥 클래스만 등록해주면 안되고 @Controller@Component가 있어야 빈으로 등록이 됨


@RunWith(SpringRunner.class)
// @WebMvcTest({EventFormatter.class, EventController.class})
@WebMvcTest({EventConverter.StringToEventConverter.class, EventController.class})
public class EventControllerTest {

    @Autowired
    MockMvc mockMvc;

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

기본적으로 등록된 Converter들을 보는 방법

@Component
public class AppRunner implements ApplicationRunner {

    @Autowired
    ConversionService conversionService;

    @Override
    public void run(ApplicationArguments args) throws Exception {
        System.out.println(conversionService);
        System.out.println(conversionService.getClass().toString());
    }
}
728x90

댓글

💲 추천 글