본문 바로가기
기술 공부

HandlerMethodArgumentResolver 인터페이스를 사용한 파라미터 조작

by 랼랼 2022. 4. 23.

HandlerMethodArgumentResolver 인터페이스

 

1. 개요

공식 설명은 다음과 같이 적혀있다.

/**
 * Strategy interface for resolving method parameters into argument values in
 * the context of a given request.
 *
 * @author Arjen Poutsma
 * @since 3.1
 * @see HandlerMethodReturnValueHandler
 */

 

즉, 파라미터를 주입시켜주는 전략적인 인터페이스이다.

그럼 전략적으로 파라미터를 주입시켜준다는 말은 무슨 뜻일까?
이는 파라미터를 그대로 사용하지 않고 일부 처리가 필요한 경우에 사용한다.
예를 들어 컨트롤러에서 pageable 객체를 파라미터 offset과 size를 통해 생성하고자 하려고 한다고 가정해보자.
offset과 size의 값이 내가 원하는 정상적인 값이 들어온다면 다행이지만,
만약 파라미터가 제공되지 않거나, 지정한 범위를 넘어선 값이 제공되면 난감한 상황이 발생할 것이다.
이를 방지하기 위해 offset 과 size의 값을 내가 정한 defalut 값으로 설정하고, 이를 Pageable 객체로 리턴하고 싶다.
이러한 경우, 요청한 offset과 size를 가공하여 리턴하는 HandlerMethodArgumentResolver 인터페이스를 이용한다.



2. 메서드

메서드는 2가지가 있다.

 

1)supportsParameter

/**
 * Whether the given {@linkplain MethodParameter method parameter} is
 * supported by this resolver.
 * @param parameter the method parameter to check
 * @return {@code true} if this resolver supports the supplied parameter;
 * {@code false} otherwise
 */
boolean supportsParameter(MethodParameter parameter);

파라미터를 지원할 지에 대해 검사하는 메서드이다.

 

예시 코드

@Override
public boolean supportsParameter(MethodParameter parameter) {
  return Pageable.class.isAssignableFrom(parameter.getParameterType());
}

Pageable 클래스로 받을 수 있으면 해당 파라미터에 대해 처리한다.

 

2) resolveArgument

/**
 * Resolves a method parameter into an argument value from a given request.
 * A {@link ModelAndViewContainer} provides access to the model for the
 * request. A {@link WebDataBinderFactory} provides a way to create
 * a {@link WebDataBinder} instance when needed for data binding and
 * type conversion purposes.
 * @param parameter the method parameter to resolve. This parameter must
 * have previously been passed to {@link #supportsParameter} which must
 * have returned {@code true}.
 * @param mavContainer the ModelAndViewContainer for the current request
 * @param webRequest the current request
 * @param binderFactory a factory for creating {@link WebDataBinder} instances
 * @return the resolved argument value, or {@code null} if not resolvable
 * @throws Exception in case of errors with the preparation of argument values
 */
@Nullable
Object resolveArgument(MethodParameter parameter, @Nullable ModelAndViewContainer mavContainer,
        NativeWebRequest webRequest, @Nullable WebDataBinderFactory binderFactory) throws Exception;

파라미터에 대한 서비스 로직을 처리하는 곳이다.

주어진 요청의 메서드 파라미터를 적당한 값(객체)으로 처리하여 리턴한다. 

 

예시 코드

@Override
public Object resolveArgument(MethodParameter parameter, ModelAndViewContainer mavContainer,
        NativeWebRequest webRequest, WebDataBinderFactory binderFactory) throws Exception {
    String offsetString = webRequest.getParameter("offset");
    String sizeString = webRequest.getParameter("size");

    long offset = isNumber(offsetString) ? Long.parseLong(offsetString) : DEFAULT_OFFSET;
    int size = isNumber(sizeString) ? Integer.parseInt(sizeString) : DEFAULT_SIZE;
    return new SimplePageRequest(offset, size);
}

private boolean isNumber(String parameter){
    String regex = "^[0-9]*$";
    return parameter!=null&&parameter.matches(regex);
}

요청된 파라미터 offset과 size에 대해 숫자인지에 대해 검사하고,

통과한 경우 주어진 값을,

해당되지 않는다면 설정한 default 값으로 변경하여

SimplePageRequest 객체로 리턴한다.

 

3. 사용법

 

1) 클래스 생성

HandlerMethodArgumentResolver를 상속한 클래스를 생성하고 이를 구현한다.

(메서드는 위에 코드들을 참고)

public class SimplePageRequestHandlerMethodArgumentResolver implements HandlerMethodArgumentResolver

2) WebMvcConfig 등록

 

커스텀한 HandlerMethodArgumentResolver  클래스를 사용하기 위해서는

WebMvcConfig에 HandlerMethodArgumentResolver를 구현한 클래스를 등록해주어야 한다.

@Configuration
public class WebMvcConfigure implements WebMvcConfigurer {

  @Bean
  public SimplePageRequestHandlerMethodArgumentResolver
   simplePageRequestHandlerMethodArgumentResolver() {
    SimplePageRequestHandlerMethodArgumentResolver resolver
     = new SimplePageRequestHandlerMethodArgumentResolver();
   
    return resolver;
  }

  @Override
  public void addArgumentResolvers(List<HandlerMethodArgumentResolver> argumentResolvers) {
    argumentResolvers.add(simplePageRequestHandlerMethodArgumentResolver());
  }

}

addArgumentResolvers 메서드를 통해

파라미터에 대해 구현한 Resolver 처리를 추가한다.

 

3) 컨트롤러에서 파라미터 받기

 

@GetMapping
public ApiResult<?> findAll(@AuthenticationPrincipal JwtAuthentication user, Pageable pageable){
  return success(orderService.findAll(user.id, pageable.getSize(), pageable.getOffset()));
}

파라미터를 클래스형태로 받아올 수 있다.

파라미터는 HandlerMethodArgumentResolver를 거쳐 가공되어 pageable 객체에 들어있다.

 

 

반응형

댓글