데이터 처리를 하다보면 타입을 바꿔야 되는 상황이 자주 생긴다.

 

예를 들어 문자 '10'을 숫자 10으로 바꿔야 되는 상황이 있을때 스프링부트에서는 어떻게 하는지 정리하였다.

 

public void helloV1(HttpServletRequest request) {
	String data = request.getParameter("data"); //문자 타입 조회
	Integer intValue = Integer.valueOf(data); //숫자 타입으로 변경
   }

위와 같이 직접 형변환을 해줄수도 있지만 형변환을 편하게 하는 방법들을 알아보자.

public String helloV2(@RequestParam Integer data) {
	System.out.println("data = " + data);
	return "ok";
}

@RequestParam을 사용하면 문자 10을 숫자 10으로 편리하게 받을 수 있다.

이 외에도 @ModelAttribute, @PathVariable 에서도 적용된다.

@ModelAttribute 
UserData data

class UserData {
	Integer data;
}

/users/{userId}
@PathVariable("userId") Integer data

하지만 타입을 직접 만들어서 사용하려면 Converter를 사용하면 된다.

public class StringToIntegerConverter implements Converter<String, Integer> {

	@Override
	public Integer convert(String source) {
	log.info("convert source={}", source);
	return Integer.valueOf(source);
	}
}

String 에서 Integer로 변환하는 Converter 예시이다.

이 외에도 같은 방식으로 원하는 타입으로 변환할 수 있다.

 

스프링에서 Converter를 사용하려면 WebMvcConfigurer를 상속받아서 등록을 해줘야 한다.

@Configuration
public class WebConfig implements WebMvcConfigurer {
    @Override
    public void addFormatters(FormatterRegistry registry) {
    registry.addConverter(new StringToIntegerConverter());
    }
}

추가로 타임리프를 사용한다면 ${{...}} 를 사용해서 자동으로 컨버전 서비스를 사용해서 변환된 결과를 출력해준다. 물론 스프링과 통합 되어서 스프링이 제공하는 컨버전 서비스를 사용하므로, 직접 등록한 컨버터들을 사용할 수 있다.

<ul>
 <li>${number}: <span th:text="${number}" ></span></li> # 기존방법
 <li>${{number}}: <span th:text="${{number}}" ></span></li> # 컨버전 서비스 적용 방법
<ul>

 

추가로 Fommater 를 같이 사용할 수 있는 DefaultFormattingConversionService가 있다.

@Configuration
public class WebConfig implements WebMvcConfigurer {
    @Override
    public void addFormatters(FormatterRegistry registry) {
    registry.addConverter(new StringToIntegerConverter());

    //추가
    registry.addFormatter(new 직접만든 포매터());
    }
}
 
 
 
 

 

스프링에서는 기본적으로 자주사용되는 여러가지 포맷터가 제공되니 사용할 수 있다.

@Data
static class Form {
    @NumberFormat(pattern = "###,###")
    private Integer number;
    @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
    private LocalDateTime localDateTime;
}

위와 같이 애노테이션 기반으로 형식을 지정해서 편리하게 사용할 수 있다.

 

 

 

출처 : 인프런 mvc 강의

필터의 흐름은 다음과 같다.

 

HTTP 요청 -> WAS -> 필터 -> 서블릿 -> 컨트롤러

 

흐름에서 볼 수있듯이 필터는 http 요청을 받아서 컨트롤러에 가기전에 동작하고,

기능에 따라 컨트롤러에 접근하지 못하게 막아주는 역할을 하기도 한다.

 

필터는 서블릿에서 지원하여 Filter 인터페이스를 구현해서 등록한 뒤 사용해야한다.

  # 필터의 3가지 메서드
  init(): 필터 초기화 메서드, 서블릿 컨테이너가 생성될 때 호출된다.
  doFilter(): 고객의 요청이 올 때 마다 해당 메서드가 호출된다. 필터의 로직을 구현하면 된다.
  destroy(): 필터 종료 메서드, 서블릿 컨테이너가 종료될 때 호출된다.

 


@Slf4j
public class LogFilter implements Filter {
	@Override
	public void init(FilterConfig filterConfig) throws ServletException {
	 	log.info("log filter init");
	}
    
 	@Override
 	public void doFilter(ServletRequest request, ServletResponse response,FilterChain chain) throws IOException, ServletException {
 		HttpServletRequest httpRequest = (HttpServletRequest) request;
		String requestURI = httpRequest.getRequestURI();
 		String uuid = UUID.randomUUID().toString();
 		try {
 			log.info("REQUEST [{}][{}]", uuid, requestURI);
 			chain.doFilter(request, response);
 		} catch (Exception e) {
 			throw e;
 		} finally {
 			log.info("RESPONSE [{}][{}]", uuid, requestURI);
 		}
 	}
    
 	@Override
 	public void destroy() {
 		log.info("log filter destroy");
 	}
}

 

먼저 HTTP 요청이 오면 doFilter가 호출되고 doFilter에서 chain.doFilter(request, response)는 다음 필터가 있으면 호출하고, 없으면 서블릿을 종료하기 때문에 이 로직을 호출하지 않으면 다음 단계로 진행되지 않는다.!!

 

이후 스프링 빈을 등록하면 동작하게 된다.

@Configuration
public class WebConfig {
	@Bean
 	public FilterRegistrationBean logFilter() {
 		FilterRegistrationBean<Filter> filterRegistrationBean = new FilterRegistrationBean<>();
 		filterRegistrationBean.setFilter(new LogFilter());
 		filterRegistrationBean.setOrder(1);
 		filterRegistrationBean.addUrlPatterns("/*");
 		return filterRegistrationBean;
 	}
}

+ Recent posts