포맷터 - Formatter
보통 문자 -> 다른 타입 혹은 다른 타입 -> 문자의 변환을 많이 사용한다.
스프링에서는 포맷터라는 문자의 자동 변환 기능을 제공한다.
MyNumberFormatter.class
@Slf4j
public class MyNumberFormatter implements Formatter<Number> {
// Number는 integer, double, long 등 숫자 형태 타입의 부모
@Override
public Number parse(String text, Locale locale) throws ParseException {
log.info("text={}, locale={}", text, locale);
// "1,000" -> 1000
NumberFormat format = NumberFormat.getInstance(locale);
Number parse = format.parse(text);
return parse;
}
@Override
public String print(Number object, Locale locale) {
log.info("object={}, locale={}", object, locale);
NumberFormat instance = NumberFormat.getInstance(locale);
String format = instance.format(object);
return format;
}
}
Formatter을 implements를 한 구현체에서 parse와 print 2가지의 메서드를 구현할 수 있다.
변환을 할 객체의 타입과 Locale을 파라미터로 갖는다.
NumberFormate으로 locale의 instance를 받아오고, parse는 parse를, print는 format을 이용해서 객체 타입을 바꾼 다음에 return 해주면 된다.
포맷터의 적용
@Configuration
public class WebConfig implements WebMvcConfigurer {
@Override
public void addFormatters(FormatterRegistry registry) {
registry.addConverter(new StringToIpPortConverter());
// registry.addConverter(new StringToIntegerConverter());
registry.addConverter(new IpPortToStringConverter());
// registry.addConverter(new IntegerToStringConverter());
// 포맷터 추가
registry.addFormatter(new MyNumberFormatter());
}
}
WebConfig에 registry.addFormatter(new MyNumberFormatter());를 이용해 포맷터를 추가해주었다.
이전에 해줬던 addConverter의 주석 2개는 우선순위때문에 주석처리 해 준 것이다.
localhost:8080/hello-v2?data=10,000 로 파라미터를 넘겨주면
@GetMapping("/hello-v2") // 이전에 만들었던 매핑 메서드
public String helloV2(@RequestParam Integer data) {
System.out.println("data = " + data);
return "ok";
}
2023-03-07T16:56:47.403+09:00 INFO 4988 --- [nio-8080-exec-5] h.t.formatter.MyNumberFormatter : text=10,000, locale=ko
data = 10000
라는 로그가 찍힌다.
data로 들어올 때 문자가 아닌 integer 타입으로 들어온 것을 확인할 수 있었다.
스프링에서 제공하는 기본 포맷터
@NumberFormat : 숫자 관련 형식 지정 포맷터 사용
@DateTimeFormat : 날짜 관련 형식 지정 포맷터 사용
@Controller
public class FormatterController {
@GetMapping("/formatter/edit")
public String formatterForm(Model model) {
Form form = new Form();
form.setNumber(10000);
form.setLocalDateTime(LocalDateTime.now());
model.addAttribute("form", form);
return "formatter-form.html";
}
@PostMapping("/formatter/edit")
public String formatterEdit(@ModelAttribute Form form) {
return "formatter-view";
}
@Data
static class Form {
@NumberFormat(pattern = "###,###")
private Integer number;
@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private LocalDateTime localDateTime;
}
}
포맷터를 사용하는 클래스이다. Form이라는 객체를 만들고 @NumberFormat, @DateTimeFormat 애노테이션을 사용하고 패턴을 지정해주면 해당 형태로 타입을 변환시켜준다.
formatter-view.html
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<ul>
<li>${form.number}: <span th:text="${form.number}" ></span></li>
<li>${{form.number}}: <span th:text="${{form.number}}" ></span></li>
<li>${form.localDateTime}: <span th:text="${form.localDateTime}" ></span></li>
<li>${{form.localDateTime}}: <span th:text="${{form.localDateTime}}" ></span></li>
</ul>
</body>
</html>
타입변환이 자동으로 잘 이루어진다.
나중에 타입 변환이 필요해서 컨버터를 사용해야할 때가 있을텐데 직접 만들어서 하기에는 번거로우니까 스프링에서 제공하는 포맷터를 사용하면 효율적으로 개발을 할 수 있을 것이라 생각된다.