티스토리 뷰

Java/spring

Spring Converter

LichKing 2017. 3. 12. 16:04

얼마전 포스팅했던 Joda Time에 대해 사내발표를 진행했는데... 사내 프로젝트 내에서 Date타입으로 선언된 필드들을 Joda Time으로 변경하자는 의견이 나왔고, 다른 개발자들이 별다른 설정이나 추가코드를 작성할 필요없이 Joda Time 클래스를 사용할 수 있게 하라는 지시가 내려왔다. 이렇게까지 일을 벌일(?) 생각은 없었는데 그 작업을 맡게되었고 일단 날짜 데이터를 화면에서 보내면 LocalDate(혹은 LocalDateTime)로 자동으로 받을 수 있게끔 작업하는것부터 시작이 됐어야했다. 그 작업을 포스팅으로 남겨두려한다.


1. Spring Data Binding

일단 Spring 컨트롤러는 매개변수로 변수를 넣어놓으면 알아서 해당 타입으로 값을 갖다 쓸 수있게 되어있다.

@RequestMapping("/hello")
public String hello(int page){
return "hello";
}


인자들이 여러개가 될경우 Command 객체를 인자로 받게하면 해당 객체로 받아주기도 한다.

@RequestMapping("/hello")
public String hello(Command command){
return "hello";
}

public static class Command{
private int page;

public void setPage(int page){
this.page = page;
}

public int getPage(){
return this.page;
}
}


별 생각없이 잘 쓰고있긴한데 이제와서 생각해보면 참 신통방통한 일이 아닐 수 없다. 스프링 없이 서블릿 기반으로 게시판만 하나 만들어봤으면 알 수 있겠지만 화면에서 전달되는 데이터는 기본적으로 String 타입이기 때문이다.

HttpServletRequest 의 getParameter() 메서드는 리턴타입이 String 인 이유이다. 결국은 어디선가 형변환을 해주는곳이 있다는 얘기가 된다.


2. Converter

날짜 형태로 넘어오는 값 역시 형태가 어찌됐든 문자열로 넘어올것이고, 그 문자열을 LocalDate 타입으로 변환해주는 코드를 작성해야한다는 의미가 된다. 그 역할을 해주는게 Converter이다.

Spring core 프로젝트에 있는 Converter<S, T> 인터페이스를 구현해주면 된다. S는 input 타입이고 T는 return 타입이다.


package org.springframework.core.convert.converter;

public interface Converter<S, T> {
T convert(S var1);
}


구현은 어려운게 없다. 그저 타입변환만 해주면 되니..


/**
* Created by LichKing on 2017. 3. 12..
*/
public class StringToLocalDateConverter implements Converter<String, LocalDate> {
private static final DateTimeFormatter DATE_TIME_FORMATTER = DateTimeFormatter.ofPattern("yyyyMMdd");

@Override
public LocalDate convert(String s) {
return LocalDate.parse(s, DATE_TIME_FORMATTER);
}
}

parse() 메서드는 인자를 1개만 받는 메서드도있는데 그 경우엔 기본 패턴이 yyyy-MM-dd 이다. 기본 형태로 넘겨준다면 따로 DateTimeFormatter 객체를 만들필요는 없다.


인자에대한 empty 체크 정도는 해줘야 할것 같다.

@Override
public LocalDate convert(String s) {
if(s == null || s.isEmpty()){
return null;
}

return LocalDate.parse(s, DATE_TIME_FORMATTER);
}

값이 없을때 기본날짜를 넘겨주거나 Optional을 넘겨주거나 null을 넘겨줄지는 정책을 정해서 가면 될 것 같다.


Converter는 만들었으니 이제 이걸 등록해주자. ConverterFactory 빈을 만들어줘야한다. 현재 XML 기반의 설정파일을 사용하고있으므로 XML 설정법으로 이어가겠다.


<bean id="conversionService"
class="org.springframework.context.support.ConversionServiceFactoryBean">
<property name="converters">
<set>
<bean class="com.yong.spring.binding.StringToLocalDateConverter"/>
</set>
</property>
</bean>

빈을 생성하고

<mvc:annotation-driven conversion-service="conversionService">

서비스를 등록해주면 Converter를 통해 LocalDate로 넘어오는걸 확인할 수 있다.


@RequestMapping("/hello")
public String hello(Command command){
return "hello";
}

public static class Command{
private LocalDate date;

public void setDate(LocalDate date){
this.date = date;
}

public LocalDate getDate(){
return this.date;
}
}


#2017.04.09 추가

xml이 아닌 java 기반의 설정을 하고있다면 config 파일에 이렇게 추가해주면 된다.

@Override
public void addFormatters(FormatterRegistry registry){
registry.addConverter(new Converter<String, LocalDate>(){
@Override
public LocalDate convert(String s) {
return null;
}
});
}


나는 현재 xml기반으로 사용하고있고, 자바 설정 예제를 위해 간략히 짠거라 일단 익명 클래스 방식으로 했는데..java8을 사용한다면 xml로 설정할때처럼 따로 파일 만들필요없이 람다로 만들어놓으면 관리하기도 편할것 같기도하다(변환 코드가 짧다는 가정하에..).

@Override
public void addFormatters(FormatterRegistry registry){
registry.addConverter((String s) -> LocalDate.parse(s));
}


더 줄여서 메서드 레퍼런스로 만들어버리자

@Override
public void addFormatters(FormatterRegistry registry){
registry.addConverter((Converter<String, Object>) LocalDate::parse);
}


'Java > spring' 카테고리의 다른 글

Spring Bean 초기화/소멸  (0) 2017.11.17
static factory method를 이용한 spring bean 생성  (4) 2017.11.16
List, Map Spring Bean 생성  (0) 2017.02.24
intellij spring mvc 설정  (0) 2016.07.20
Spring DI  (0) 2016.02.23
댓글
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
«   2024/04   »
1 2 3 4 5 6
7 8 9 10 11 12 13
14 15 16 17 18 19 20
21 22 23 24 25 26 27
28 29 30
글 보관함