[Spring] HandlerMethodArgumentResolver 인터페이스

ybw·2021년 7월 8일
0

Spring

목록 보기
2/3
post-thumbnail

HandlerMethodArgumentResolver

개요

Strategy interface for resolving method parameters into argument values in the context of a given request.
주어진 요청을 처리할 때, 메소드 파라미터를 인자값들에 주입 해주는 전략 인터페이스.

@GetMapping(path = "post") 
public ApiResult<<Post>> post(
    ... 
    @RequestParam(name = "param1", required = false) String param1, 
    @RequestParam(name = "param2", required = false) String param2, 
    @RequestParam(name = "param3", required = false) String param3,
    @RequestParam(name = "param4", required = false) String param4,
    @RequestParam(name = "param5", required = false) String param5,
    ...) 

다음과 같이 Request파라미터가 많게 되면 코드를 지저분하게 작성하게 될 수 있습니다.

이를 만약,

@GetMapping(path = "post") 
public ApiResult<<Post>> post(
  ... 
  CustomParam customParam
  ...) 

이런식으로 코드를 작성한다면 간편하게 코드를 작성할 수 있다고 생각됩니다.

HandlerMethodArgumentResolver 인터페이스

public interface HandlerMethodArgumentResolver {

	boolean supportsParameter(MethodParameter parameter);

	@Nullable
	Object resolveArgument(
    		MethodParameter parameter,
            	@Nullable ModelAndViewContainer mavContainer,
		NativeWebRequest webRequest,
            	@Nullable WebDataBinderFactory binderFactory) throws Exception;

}

HandlerMethodArgumentResolver 인터페이스는 다음과 같은 추상 메서드를 가지고 있습니다.

  • supportsParameter 메서드는 현재 파라미터를 resolver가 지원하는지에 대한 boolean을 리턴합니다.

  • resolveArgument 메서드는 실제로 바인딩을 할 객체를 리턴합니다.

사용

이런 HandlerMethodArgumentResolver를 구현하여 Pageable객체를 파라미터로 사용하는 예시를 살펴 보겠습니다.

먼저, 바인딩할 객체 클래스를 선언합니다.

public class SimplePageRequest implements Pageable{

    private final long offset;

    private final int size;

    public SimplePageRequest() {
        this(0,5);
    }

    public SimplePageRequest(long offset, int size) {

        checkArgument(offset >=0, "offset must be greater or equals to zero");
        checkArgument(size >=1, "size must be greater than zero");

        this.offset = offset;
        this.size = size;
    }

    @Override
    public long getOffset() {
        return offset;
    }

    @Override
    public int getSize() {
        return size;
    }

    @Override
    public String toString() {
        return new Long(offset).toString() + " " + new Integer(size).toString();
    }
}

다음으로 HandlerMethodArgumentResolver를 구현한 클래스를 만들고 각 추상메서드를 구현해줍니다.

public class SimplePageRequestHandlerMethodArgumentResolver implements HandlerMethodArgumentResolver {

    private static final String DEFAULT_OFFSET_PARAMETER = "offset";

    private static final String DEFAULT_SIZE_PARAMETER = "size";

    private static final long DEFAULT_OFFSET = 0;

    private static final int DEFAULT_SIZE = 5;

    private String offsetParameterName = DEFAULT_OFFSET_PARAMETER;

    private String sizeParameterName = DEFAULT_SIZE_PARAMETER;


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

    @Override
    public Object resolveArgument(
            MethodParameter methodParameter,
            ModelAndViewContainer mavContainer,
            NativeWebRequest webRequest,
            WebDataBinderFactory binderFactory
    ) {
        String offsetString = webRequest.getParameter(offsetParameterName);
        String sizeString = webRequest.getParameter(sizeParameterName);
        List<Integer> list = new ArrayList<>();
        
        if(offsetString != null && sizeString != null) {
            long offset = Long.parseLong(offsetString);
            int size = Integer.parseInt(sizeString);
            if(offset<0)
                offset = DEFAULT_OFFSET;
            if(size<1||size>5)
                size = DEFAULT_SIZE;
            return new SimplePageRequest(offset, size);
        }
        return new SimplePageRequest(DEFAULT_OFFSET,DEFAULT_SIZE);

    }

    public void setOffsetParameterName(String offsetParameterName) {

        this.offsetParameterName = offsetParameterName;
    }

    public void setSizeParameterName(String sizeParameterName) {
        this.sizeParameterName = sizeParameterName;
    }
}

구현한 SimplePageRequestHandlerMethodArgumentResolver를 addArgumentResolvers메서드를 통해 추가해줍니다.

@Configuration
public class WebMvcConfigure implements WebMvcConfigurer {

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

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

이제 객체를 전달하여도 파라미터에 알맞을 값을 바인딩하여 요청할 수 있습니다.

    @GetMapping
    public ApiResult<List<OrderDto>> findAll(Pageable simplePageRequest) {
        return success(orderService.findAll(simplePageRequest).stream()
        		...
                .collect(toList()));
    }
profile
유병우

0개의 댓글