애노테이션 기반의 컨트롤러는 매우 다양한 파라미터를 사용할 수 있다.
HttpServletRequest
,Model
, 등등 큰 유연함을 가지고 있다.
이렇게 파리미터를 유연하게 처리할 수 있는 이유가 ArgumentResolver
덕분이다.
RequestMappingHandlerAdapter
는 ArgumentResolver
를 호출해서 컨트롤러(핸들러)가 필요로 하는 다양한 파라미터의값(객체)를 생성한다. 그리고 이렇게 파라미터의 값이 모두 준비되면 컨트롤러를 호출하면서 값을 넘겨준다.
public interface HandlerMethodArgumentResolver {
boolean supportsParameter(MethodParameter parameter);
@Nullable
Object resolveArgument(MethodParameter parameter, @Nullable
ModelAndViewContainer mavContainer,
NativeWebRequest webRequest, @Nullable WebDataBinderFactory
binderFactory) throws Exception;
}
ArgumentResolver
의 supportsParamete()
를 호출해서 해당 파라미터를 지원하는지 체크하고, 지원하면 resolveArgumenr()
를 호출해서 파라미터의 값(객체)를 생성한다. 그리고 컨트롤러 호출시 넘어가는 것이다.
HandlerMethodReturnValueHandler
를 줄여서 ReturnValueHandler
라 부른다. 응닶값을 변환하고 처리한다.그래서 String으로 뷰이름을 반환해도, 동작하는 이유가 ReturnValueHandler
덕분이다
요청의 경우
@RequestBody
를 처리하는 ArgumentResolver
, HttpEntity
를 처리하는 ArgumentResolver
가 있다. ArgumentResolver
들이 HTTP 메시지 컨버터를 사용해서 필요한 객체를 사용하는 것이다.
@RequestMapping
,@ResponseMapping
에는 RequestResponseBodyMethodProcessor
라는 ArgumentResolver
가 있다. 코드로 ArgumentResolver
에서 HTTP 메시지 컨버터가 쓰이는 곳을 봐보자.
RequestResponseBodyMethodProcessor
readWithMessageConverters()
가 있는데 Object
라는 파라미터 객체를 생성해서 전달해준다. 이때
readWithMessageConverters()
를 보면
HTTP 메시지 컨버터는 요청의 경우 @RequestMapping
이 달린 파라미터일 경우 쓰이며 canRead()
로 읽을 수 있는지 체크하고, read()
로 메시지 바디를 읽는다.
응답의 경우
@ResponseBody
와 HttpEntity
를 처리하는 ReturnValueHandler
가 있다. 그리고 여기에 HTTP 메시지 컨버터를 사용해서 응답 메시지 바디를 만든다.