프로그래머스 강의 과제를 하던 중 클라이언트에서 보낸 쿼리 파라미터 값이 컨트롤러 파라미터에 바인딩이 되지 않아서 삽질을 했다. Spring 프레임워크에서 지원하는 Pageable 인터페이스를 사용하지 않고, 직접 Pageable 인터페이스를 생성해서 사용했다.
클라이언트에서 쿼리 파라미터로 값 보내기
포스트 목록을 조회하는데, 쿼리 파라미터 값으로 offset 값은 0, limit 값은 5를 보내고 있다.
컨트롤러에서 포스트 목록 조회 메서드
컨트롤러에서는 리스트 조회를 하기 위한 메서드를 다음과 같이 구현했다. 이 때, Pageable 인터페이스는 직접 생성했다.
@RestController
@RequestMapping("api")
public class PostRestController {
@GetMapping(path = "user/{userId}/post/list")
@ApiOperation(value = "포스트 목록 조회")
public ApiResult<List<Post>> posts(
@AuthenticationPrincipal JwtAuthentication authentication,
@PathVariable
Long userId,
Pageable pageable
) {
return new ApiResult<>(postService.findAll(
Id.of(User.class, userId),
authentication.id,
pageable.getOffset(),
pageable.getLimit()));
}
}
클라이언트에서 보낸 요청 값을 이용하지 않고, 기본 생성자에 설정한 기본값으로 인스턴스가 생성되는 문제가 있었다. 왜 요청한 값을 받지 못하는 것일까? 구글 검색을 하던 중 HandlerMethodArgumentResolver 인터페이스를 사용해야 하는 것을 알 수 있었다.
HandlerMethodArgumentResolver
HandlerMethodArgumentResolver 인터페이스는 컨트롤러에서 파라미터를 바인딩 해주는 역할을 수행한다. 특정 클래스 또는 어노테이션에 대해서 파라미터를 처리해야 하는 경우에 사용한다.
HandlerMethodArgumentResolver 인터페이스에는 두 개의 메서드가 선언되어 있다.
public interface HandlerMethodArgumentResolver {
boolean supportsParameter(MethodParameter parameter);
@Nullable
Object resolveArgument(MethodParameter parameter,
@Nullable ModelAndViewContainer mavContainer,
NativeWebRequest webRequest,
@Nullable WebDataBinderFactory binderFactory) throws Exception;
}
- supportsParameter 메서드 : 바인딩 하고자 하는 타겟팅 클래스를 지정한다.
- resolveArgument 메서드 : 요청한 값을 타겟팅 객체에 바인딩 등 조작한다.
PageableMethodArgumentResolver 생성
PageableMethodArgumentResolver 클래스를 다음과 같이 생성한다. supportsParameter에서는 바인딩 하고자 하는 클래스인지 체크하고, resolveArgument 메서드에서는 바인딩 될 클래스의 인스턴스를 생성한다. 지금은 요청으로 넘어온 값을 단순히 타입만 변환해서 사용하고 있지만, 값에 대한 유효성 체크 등 여러 로직이 더 추가되어야 한다.
public class SimplePageableHandlerMethodArgumentResolver implements HandlerMethodArgumentResolver {
@Override
public boolean supportsParameter(MethodParameter parameter) {
return Pageable.class.isAssignableFrom(parameter.getParameterType());
}
@Override
public Object resolveArgument(MethodParameter parameter,
ModelAndViewContainer mavContainer,
NativeWebRequest webRequest,
WebDataBinderFactory binderFactory
) {
String offsetString = webRequest.getParameter("offset");
String limitString = webRequest.getParameter("limit");
int offset = Integer.valueOf(offsetString);
int limit = Integer.valueOf(limitString);
return new SimplePageable(offset, limit);
}
}
Custom ArgumentResolver 등록
HandlerMethodArgumentResolver 인터페이스를 구현한 클래스를 생성했으면, Spring MVC에서 알 수 있도록 등록해주는 작업을 반드시 해야한다.
WebMvcConfigurer 인터페이스를 구현한 클래스에서 addArgumentResolvers 메서드를 오버라이드(재정의) 한다.
HandlerMethodArgumentResolver 인터페이스를 구현한 SimplePageableHandlerMethodArgumentResolver 클래스를 Bean으로 등록하고, resolvers 리스트에 추가한다.
@Configuration
public class WebMvcConfigure implements WebMvcConfigurer {
// 빈 생성
@Bean
public SimplePageableHandlerMethodArgumentResolver simplePageableResolver() {
return new SimplePageableHandlerMethodArgumentResolver();
}
@Override
public void addArgumentResolvers(List<HandlerMethodArgumentResolver> resolvers) {
resolvers.add(simplePageableResolver())
}
}
'Spring' 카테고리의 다른 글
Spring Core 라이브러리 이용해서 Properties 파일 데이터 읽기 (0) | 2019.05.28 |
---|---|
Spring Camp 2019 강의 자료 모음 (0) | 2019.05.06 |
Spring Boot 배너 만들기 (0) | 2019.05.04 |
REST API 문서 자동화 도구 Swagger 참고 문서 (0) | 2019.05.04 |
Spring Boot에서 JSP 사용하기 (5) | 2019.04.22 |
댓글