컨버터는 타입에 제한이 없다.
근데 웹으로써 생각해봤을 때, 대부분의 컨버팅이 필요한 상황은 문자 <-> 객체 혹은 타입 이다.
거기에서 그칠 뿐 아니라, 1000 -> "1,000"이라던지, 아니면 날짜 포맷에 맞춘다던지.
그래서,
포맷터 라는 게 있다.
이거는 객체 <-> 문자, 타입 <-> 문자 등 문자에 특화된 인터페이스이다.
게다가 Locale, 현지화와 연동하여 사용할 수도 있게끔 지원해 준다.
실제 포맷터 인터페이스는
public interface Formatter<T> extends Printer<T>, Parser<T> {
}
이렇게 생겼다.
Printer는 객체 -> 문자인 인터페이스이고,
Parse는 문자 -> 객체인 인터페이스이다.
각자 들어가서 보면
@FunctionalInterface
public interface Printer<T> {
String print(T object, Locale locale);
}
@FunctionalInterface
public interface Parser<T> {
T parse(String text, Locale locale) throws ParseException;
}
Locale을 받는다.
여튼, 상속받아서 한번 만들어 봤다.
public class MyNumberFormatter implements Formatter<Number> {
@Override
public Number parse(String text, Locale locale) throws ParseException {
String clearText = text.replaceAll(",","");
return Integer.parseInt(clearText);
}
@Override
public String print(Number object, Locale locale) {
if((int)object < 999) return String.valueOf(object);
StringBuffer intTOstr = new StringBuffer(String.valueOf(object));
for(int i = intTOstr.length() - 3; i >= 0; i -= 3){
intTOstr.insert(i,",");
}
return intTOstr.toString();
}
}
Formatter<Number> 어차피 한쪽은 문자열이라 다른 한쪽의 대상 타입만 쓰면 된다.
Number는 Integer, Float등의 상위 이다.
대충 이렇게 하긴 했는데.. 물론 잘 된다. 근데 이건 한국 기준이다.
이렇게 구현해 보니까 괜히 로컬을 인자로 받는 게 아니었다.
public class FormatterTest {
@Test
public void intToString(){
MyNumberFormatter formatter = new MyNumberFormatter();
int num1 = 100;
int num2 = 1000;
String intToStr1 = formatter.print(num1, null);
String intToStr2 = formatter.print(num2, null);
assertThat(intToStr1).isEqualTo("100");
assertThat(intToStr2).isEqualTo("1,000");
}
@Test
public void StringToInt() throws ParseException {
MyNumberFormatter formatter = new MyNumberFormatter();
String str = "1,000,000";
Number num = formatter.parse(str,null);
assertThat(num).isEqualTo(1000000);
}
}
내가 짠 테스트 코드는 이러 하고,
선생님의 로직에 따라 (이미 사실 이러 한 범용적인 것은 자바 및 스프링에서 제공해 준다.)
public class MyNumberFormatter implements Formatter<Number> {
@Override
public Number parse(String text, Locale locale) throws ParseException {
NumberFormat format = NumberFormat.getInstance(locale);
return format.parse(text);
}
@Override
public String print(Number object, Locale locale) {
NumberFormat format = NumberFormat.getInstance(locale);
return format.format(object);
}
}
NumberFormat.getInstance(locale) 해서 로컬에 맞는 정보로 setting된 NumberFormat의 객체를 가져오고,
NumberFormat.parse(문자)
문자 -> Number
(여기선 Long 타입으로 반환됨.)
NumberFormat.format(Number)
Number -> 문자
로컬 타입에 맞게 바뀐다.
테스트코드는 반환타입을 Long타입인 1000000L로 바꾸면 문제없다.
'스프링 > 4. 스프링 MVC-2' 카테고리의 다른 글
82. 포맷터 웹 어플리케이션(스프링, 컨버전서비스)에 등록 (0) | 2023.09.24 |
---|---|
81. 포맷터 스프링(컨버전서비스)에 등록 (0) | 2023.09.24 |
79. 컨버터를 뷰 템플릿에 적용 (0) | 2023.09.23 |
78. 컨버전서비스 실제 사용 (0) | 2023.09.23 |
77. 컨버전 서비스 (0) | 2023.09.23 |