요청 매핑 핸들러 어댑터 구조
Spring MVC 구조
- HTTP 메시지 컨버터는 스프링 MVC 어디쯤에서 사용되는 것일까?
- @RequestMapping을 처리하는 핸들러 어댑터인 RequestMappingHandlerAdapter에 있다.
RequestMappingHandlerAdapter 동작 방식
- 컨트롤러의 파라미터, 애노테이션 정보를 기반으로 전달 데이터를 생성한다.
- 컨트롤러를 호출한다.
- 컨트롤러의 반환 값을 변환한다.
ArgumentResolver
- 애노테이션 기반의 컨트롤러는 다양한 파라미터를 사용할 수 있다.
- HttpServletRequest, Model은 물론이고 @RequestParam, @ModelAttribute 같은 애노테이션 그리고 @RequestBody HttpEntity 같은 HTTP 메시지를 처리하는 부분까지 매우 큰 유연함을 보여주었다.
- 이렇게 파라미터를 유연하게 처리할 수 있는 이유가 바로 ArguemntResolver 덕분이다.
- 애노테이션 기반 컨트롤러를 처리하는 RequestMappingHandlerAdapter는 바로 이 ArguementResolver를 호출해서 핸들러(컨트롤러)가 필요로 하는 다양한 파라미터 값(객체)을 생성한다.
- 이렇게 파라미터의 값이 모두 준비되면 핸들러(컨트롤러)를 호출하면서 값을 넘겨준다.
ArguementResolver 동작 방식
public interface HandlerMethodArgumentResolver {
boolean supportsParameter(MethodParameter parameter);
@Nullable
Object resolveArgument(MethodParameter parameter, @Nullable ModelAndViewContainer mavContainer,
NativeWebRequest webRequest, @Nullable WebDataBinderFactory binderFactory) throws Exception;
- ArgumentResolver의 supportsParamter()를 호출해서 해당 파라미터를 지원하는지 체크한다.
- 지원하면 resolveArgument()를 호출해서 실제 객체를 생성한다.
- 그리고 이렇게 생성된 객체가 컨트롤러 호출 시 넘어간다.
ReturnValueHandler
- HandleMethodReturnValueHandler를 줄여서 ReturnValueHandler라 부른다.
- ArguementResolver와 비슷한데 이것은 응답 값을 변환하고 처리한다.
- 컨트롤러에서 String으로 뷰 이름을 반환해도 동작하는 이유가 바로 ReturnValueHandler 덕분이다.
- 스프링은 10여개가 넘는 ReturnValueHandler를 지원한다.
- ex) ModelAndView, @ResponseBody, HttpEntity, String ...
HTTP 메시지 컨버터
HTTP 메시지 컨버터 위치
- HTTP 메시지 컨버터를 사용하는 @RequestBody도 컨트롤러가 필요로 하는 파라미터의 값에 사용된다.
- @ResponseBody의 경우도 컨트롤러의 반환 값을 이용한다.
- 요청의 경우 @RequestBody를 처리하는 ArgumentResolver가 있고 HttpEntity를 처리하는 ArgumentResolver가 있다.
- 이 ArgumentResolver 들이 HTTP 메시지 컨버터를 사용해서 필요한 객체를 생성한느 것이다.
- 응답의 경우 @ResponseBody와 HttpEntity를 처리하는 ReturnValueHandler가 있다.
- 그리고 여기에서 HTTP 메시지 컨버터를 호출해서 응답 결과를 만든다.
- 스프링 MVC는 @RequestBody, @ResponseBody가 있으면 RequestResponseBodyMethodProcessor(ArgumentResolver)
- HttpEntity가 있으면 HttpEntityMethodProcessor(ArgumentResolver)를 사용한다.
확장
- 스프링이 필요한 대부분의 기능을 제공하기 때문에 실제 기능을 확장할 일이 많지는 않다.
- 기능 확장은 WebMvcConfigurer를 상속 받아서 스프링 빈으로 등록하면 된다.
@Bean
public WebMvcConfigurer webMvcConfigurer() {
return new WebMvcConfigurer() {
@Override
public void addArgumentResolvers(List<HandlerMethodArgumentResolver> resolvers) {
//...
}
@Override
public void extendMessageConverters(List<HttpMessageConverter<?>> converters) {
//...
}
};
}