ConversionService란 이전에 우리가 Convert Interface를 상속받아 구현했던 Converter들을 등록해서 사용할 수 있게 제공해주는 interface이다. 바로 사용해서 확인해보자.
public class ConversionServiceTest {
@Test
void conversionService(){
DefaultConversionService conversionService = new DefaultConversionService();
conversionService.addConverter(new StringToIntegerConverter());
conversionService.addConverter(new IntegerToStringConverter());
conversionService.addConverter(new StringToIpPortConverter());
conversionService.addConverter(new IpPortToStringConverter());
Assertions.assertEquals(conversionService.convert("10", Integer.class),10);
Assertions.assertEquals(conversionService.convert(10, String.class),"10");
IpPort ipPort = conversionService.convert("127.0.0.1:8080", IpPort.class);
Assertions.assertEquals(ipPort,new IpPort("127.0.0.1", 8080));
String ipPortString = conversionService.convert(new IpPort("127.0.0.1", 8080), String.class);
Assertions.assertEquals(ipPortString, "127.0.0.1:8080");
}
}
다음과 같이 테스트 코드를 작성하고 실행해보면
다음과 같이 자동으로 등록되어 사용할 때 Service가 자동으로 찾아서 변환한 뒤 반환해주는 작업이 진행되는 것을 알 수 있다.
ConversionService를 통해 ISP(Interface Segregation Principal) 인터페이스 분리 원칙을 지킬 수 있게 되는데. 우리는 메서드에 의존하지 않고 ConversionService.convert() 라는 메서드 하나로 모든 변환 메서드를 사용할 수 있기 때문이다.
스프링에는 SOLID가 잘 적용되어 있는 예제들을 많이 볼 수 있다. 해당 interface도 그 예제 중 하나이니 참고해두면 좋다!
@Configuration
public class WebConfig implements WebMvcConfigurer {
@Override
public void addFormatters(FormatterRegistry registry) {
registry.addConverter(new StringToIntegerConverter());
registry.addConverter(new IntegerToStringConverter());
registry.addConverter(new IpPortToStringConverter());
registry.addConverter(new StringToIpPortConverter());
}
}
Spring에 우리가 만든 Converter들을 등록해주자. 위 코드와 같이 addFormatters() 메서드를 오버라이드 해주면 끝난다.
http://localhost:8080/hello-v2?data=2 url로 요청하게 되면 원래 잘 변환되어 나오긴 했던 코드지만 이전과 다른점은 우리가 등록했던 Converter가 더 우선순위를 가지며 해당 Converter가 동작했다는 것을 알수 있다.
그럼 Spring에서 기본 제공해주지 않은 IpPort와 같은 Class로 테스트해보자.
@RestController
public class HelloController {
...
@GetMapping("/ip-port")
public String helloV3(@RequestParam IpPort ipPort){
System.out.println("ipPort.getIp() = " + ipPort.getIp());
System.out.println("ipPort.getPort() = " + ipPort.getPort());
return "ok";
}
}
Controller를 추가하고
http://localhost:8080/ip-port?ipPort=127.0.0.1:8080 url로 요청해주면
잘 동작하는 것을 확인할 수 있다.
해당 과정은
@RqeustParam
뿐만 아니라@RequestParam
에서도 잘 동작한다.@RequestParam
을 처리한ㄴ ArgumentResolver인 RequestParamMethodArgumentResolver에서 ConversionService를 사용하여 타입을 변환하는 내부 과정이 있는데. 더 깊이 확인하고 싶으면 IpPortConverter에 디버그를 찍어 보면 된다!