특정 객체 Converter 만들기
Converter 인터페이스를 구현하여 변환을 원하는 객체, 결과 순으로 입력한다.
- ex) IP, port를 변수로 가지고 있는 IpPort 객체를 String으로 변환해보자.
- 원하는 객체 생성 (IpPort)
@Getter @EqualsAndHashCode public class IpPort { private String ip; private int port; public IpPort(String ip, int port) { this.ip = ip; this.port = port; } }
@EqualsAndHashCode
: @Data를 등록하면 자동으로 생성되는 롬복 제공 기능이다 객체가 같은지 equals를 제공해준다.
- IpPort 객체를 원하는 객체로 변환 Converter 생성
@Slf4j
public class IpPortToStringConverter implements Converter<IpPort,String> {
@Override
public String convert(IpPort source) {
log.info("converter source={}", source);
return source.getIp() + ":" + source.getPort();
}
}
converter
: 변환 메서드
public interface Converter<S, T> {
@Nullable
T convert(S source);
}
Converter 테스팅
단순히 객체를 new 해서 convert 기능을 사용하면 된다.
@Test
void IpPortToString() {
StringToIpPortConverter converter = new StringToIpPortConverter();
IpPort result = converter.convert("127.0.0.1:8080");
assertThat(result).isEqualTo(new IpPort("127.0.0.1", 8080));
}
제작한 Converter
를 ConversionService
에 등록하여 사용하기
매 번 모든 컨버터를 개별적으로 사용하는 것 보다,
일괄적으로 등록하여 사용하는게 더 작업에 효율적이다. 일괄로 묶어주는 일을 해주는 것이
큰 장점으로는 사용자가 등록된 컨버터들에 대한 구체적인 정보를 몰라도,
conversionService만으로 사용할 수 있다.
ConversionService
이다.
ConversionService 인터페이스
public interface ConversionService {
boolean canConvert(@Nullable Class<?> sourceType, Class<?> targetType);
<T> T convert(@Nullable Object source, Class<T> targetType);
canConvert
: 컨버팅이 가능한가convert
: 변환
예시
Bean 등록 방법
conversionService를 생성하며, 여기에 내가 원하는 객체 변환기를
등록하기 위해서, @Bean 등록을 해줄 필요가 있다.(이미 스프링에서 내부에서 사용중이기 때문에,)
@Configuration
@RequiredArgsConstructor
public class WebMvcConfiguration {
@Bean(name="conversionService") //빈 등록
public ConversionService getConversionService() {
ConversionServiceFactoryBean bean = new ConversionServiceFactoryBean(); //팩토리 생성
Set<Converter> converters = new HashSet<>(); //컨버터 담은 Set 생성
converters.add(new IpPortToStringConverter());
converters.add(new StringToIpPortConverter());
bean.setConverters(converters); //add converters
bean.afterPropertiesSet();
return bean.getObject();
}
}
bean.afterPropertiesSet()
: 프로퍼티를 세팅하고 기본적인 생성 작업을 담당한다.
나와 같은 xml 세대를 위해 이해가 쉽게 xml버젼도
<bean id="conversionService" class="org.springframework.context.support.ConversionServiceFactoryBean">
<property name="converters">
<set>
<bean class="example.MyCustomConverter"/>
</set>
</property>
</bean>
- converters 프로퍼티에 set으로 커스텀 컨버터들을 넣어준다.
WebMvcConfiguration으로 추가하기
@Configuration
@RequiredArgsConstructor
public class WebMvcConfiguration implements WebMvcConfigurer {
@Override
public void addFormatters(FormatterRegistry registry) {
registry.addConverter(new IpPortToStringConverter());
registry.addConverter(new StringToIpPortConverter());
}
}
implements WebMvcConfigurer
: WebMvcConfigurer에는 이미 Converter 등록 기능이 있다.addFormatters
: Converter를 등록
conversionService 테스트
등록된 것 확인
@SpringBootTest
public class ConversionServiceTest {
@Autowired
ConversionService conversionService;
@Test
void conversionService() {
//등록
IpPort result = conversionService.convert("127.0.0.1:8080", IpPort.class);
Assertions.assertThat(result).isEqualTo(new IpPort("127.0.0.1", 8080));
}
}
@Autowired ConversionService conversionService
: 내가 빈으로 등록한 (빈 네임 : conversionService) 가 주입된다.
변환에 성공했다. 등록이 성공적으로 완료됐다는 의미.
컨버터를 등록했기 때문에, 내 커스텀 객체가 자동 변환이 가능하게 됐다.
Api 객체 받기에 사용 가능하다. (약간 )
@GetMapping("/test")
public String testing(@RequestParam IpPort ipPort) {
System.out.println("ipPort.getPort() = " + ipPort.getPort());
System.out.println("ipPort.getIp() = " + ipPort.getIp());
return "ok";
}
http://localhost:8080/test?ipPort=127.0.0.1:8080
로 테스트시 결과
잘 변환된 모습
View 에서 thymeleaf Converting 이용 출력하기
기본적으로 타임리프는 ConversionService가 지원된다.
${...}
: 우리가 아는 일반적인 변수 표현식${{...}}
: 컨버젼 서비스 적용하여 변환된 값이 나온다.
우리가 만든 IpPort 객체를 Thymeleaf로 변환
${ipPort} vs ${{ipPort}}
Controller에서 Model에
addAttribute("ipPort",new IpPort("127.0.0.1",8080));
하여 Rest가 아닌 View에 담아 넘기는 경우,
<span th:text="${ipPort}">
<span th:text="${{ipPort}}">
- ${ipPort}는 객체 프록시 그대로 보여준다.
- ${{ipPort}}는 컨버젼 서비스를 사용하란 명령이므로 127.0.0.1:8080 으로 보여준다.
Form에서 컨버팅 사용하기
<form th:obejct="${form}" th:method="post">
<input type="text" th:field="*{ipPort}"><br/>
<input type="text" th:value="*{ipPort}">
</form>
*{}
: th:object가 있으면, 그 변수를 포함하는 값을 나타낸다.th:field
: 컨버젼 서비스를 이미 포함하고 있어서 ipPort 실 데이터를 보여준다.
Form에서 컨버팅 사용법
- @GetMapping으로 form View로 넘겨주기
- form에서 위처럼 작성해서 Controller에서 ipPort 변환 컨버터를 사용하여
자동 변환 시켜주기 - 그 컨트롤러에서 원하는 곳으로 보내기 (View라면 ${{ipPort}}로 표현)
'스프링 > MVC' 카테고리의 다른 글
[MVC 기초] Spring Boot File Upload/Download 구현하기 (+ multipart/form-data 설명) (0) | 2022.07.26 |
---|---|
[MVC 기초]Spring Formatter Date, Number 원하는 포맷으로 변환하기 (0) | 2022.07.26 |
[MVC 기초] API 예외 처리 @ExceptionHandler + 스프링 Resolver 동작 원리 (0) | 2022.07.07 |
[MVC 기본] 공통 관심사항을 처리하는 방법 (Servlet Filter, Spring Interceptor를 구현하며) (0) | 2022.06.06 |
[MVC 기초] 패키지 구조 설계 domain vs web package (0) | 2022.05.29 |