RequestMappingHandlerAdapter 구조

YH·2023년 4월 22일
0

✅ 들어가기 전

  • 이전 포스트에서 정리했던 HTTP MessageConverter가 어느 시점에 어디에서 실행되는 것인가?
  • 위 질문에 대한 답을 얻기 위해 RequestMappingHandlerAdapter 구조 및 동작 방식부터 알아본다.

✅ RequestMappingHandlerAdapter 동작 방식

✔️ ArgumentResolver

  • @Controller 기반의 컨트롤러는 매우 다양한 파라미터를 사용할 수 있다. HttpServletRequest, Model, @RequestParam, @ModelAttribute, @RequestBody, HttpEntity 등등..
  • 이렇게 유연하게 파라미터를 처리할 수 있는 이유가 바로 ArgumentResolver 덕분이다.
  • RequestMappingHandlerAdapterArgumentResolver를 호출해서 컨트롤러(핸들러)가 필요로 하는 다양한 파라미터 값(객체)를 생성하여 컨트롤러를 호출하면서 넘겨 준다.
  • 스프링에서는 30개가 넘는 ArgumentResolver를 기본으로 제공한다.

💡가능한 파라미터 목록은 아래 공식 메뉴얼 확인


✔️ HandlerMehtodArgumentResolver(줄여서 ArgumentResolver) 인터페이스

public interface HandlerMethodArgumentResolver {

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

✔️ ArgumentResolver 동작 방식

  • supportParameter()를 호출해서 해당 파라미터를 지원하는지 체크
  • 지원하면 resolveArgument()를 호출해서 실제 객체를 생성
  • 컨트롤러 호출 시 생성된 객체가 컨트롤러로 전달된다.

💡 HandlerMehtodArgumentResolver 인터페이스를 확장해서 커스텀 ArgumentResolver를 만들 수도 있다.

✔️ ReturnValueHandler

  • HandlerMethodReturnValueHandler를 줄여서 ReturnValueHandler라고 부름
  • 응답 값을 변환하고 처리하는 기능
  • 스프링에서 10 여개가 넘는 ReturnValueHandler를 지원한다.

💡가능한 응답 값 목록은 아래 공식 메뉴얼에서 확인

✅ HTTP MessageConverter 위치

  • 요청의 경우
    • @RequestBody를 처리하는 ArgumentResolver가 있고, HttpEntity를 처리하는 ArgumentResolver가 있다. 이 ArgumentResolver들이 HTTP MessageConverter를 사용해서 필요한 객체를 생성한다.
  • 응답의 경우
    • @ResponseBody와 HttpEntity를 처리하는 ReturnValueHandler가 있다. 이 ReturnValueHandler가 HTTP MessageConverter를 호출해서 응답 결과를 만든다.

✔️ 확장

  • 스프링은 HandlerMethodArgumentResolver, HandlerMethodReturnValueHandler, HttpMessageConverter 를 모두 인터페이스로 제공하므로 언제든 기능 확장이 가능하다.
  • 대부분의 기능을 스프링에서 제공하기 때문에 확장할 일은 많지 않지만 필요한 경우, WebMvcConfigurer를 상속받아서 스프링 빈으로 등록하면 된다.
@Bean
public WebMvcConfigurer webMvcConfigurer() {
	return new WebMvcConfigurer() {
        @Override
        public void addArgumentResolvers(List<HandlerMethodArgumentResolver> resolvers) {
            //...
        }
    
        @Override
        public void extendMessageConverters(List<HttpMessageConverter<?>> converters) {
            //...
        }
	};
}
profile
하루하루 꾸준히 포기하지 말고

0개의 댓글