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
...)
이런식으로 코드를 작성한다면 간편하게 코드를 작성할 수 있다고 생각됩니다.
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()));
}