스프링 MVC 동작 원리(7) : DispatcherServlet 1부

de_sj_awa·2021년 6월 26일
0

어떻게 하면 핸들러를 애노테이션으로 등록할 수 있는가?

7. DispatcherServlet 1부

DispatcherServlet 초기화

  • 다음의 특별한 타입의 빈들을 찾거나, 기본 전략에 해당하는 빈들을 등록한다. (전략 패턴 적용)
  • HandlerMapping: 핸들러를 찾아주는 인터페이스
  • HandlerAdapter: 핸들러를 실행하는 인터페이스
  • HandlerExceptionResolver
  • ViewResolver
  • ...

DispatcherServlet 동작 순서
1. 요청을 분석한다. (로케일, 테마, 멀티파트 등)
2. (핸들러 맵핑에게 위임하여) 요청을 처리할 핸들러를 찾는다.
3. (등록되어 있는 핸들러 어댑터 중에) 해당 핸들러를 실행할 수 있는 “핸들러 어댑터”를 찾는다.
4. 찾아낸 “핸들러 어댑터”를 사용해서 핸들러의 응답을 처리한다.

  • 핸들러의 리턴값을 보고 어떻게 처리할지 판단한다.
  • 뷰 이름에 해당하는 뷰를 찾아서 모델 데이터를 랜더링한다.
  • @ResponseBody가 있다면 Converter를 사용해서 응답 본문을 만들고.
  1. (부가적으로) 예외가 발생했다면, 예외 처리 핸들러에 요청 처리를 위임한다.
  2. 최종적으로 응답을 보낸다.

HandlerMapping

  • RequestMappingHandlerMapping
    HandlerAdapter
  • RequestMappingHandlerAdapter

Dispatcher.class

doService -> doDispatch -> mappedHandler = getHandler(processedRequest); (핸들러를 찾아오는 부분)

@Nullable
protected HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception {
    if (this.handlerMappings != null) {
        for (HandlerMapping mapping : this.handlerMappings) {
            HandlerExecutionChain handler = mapping.getHandler(request);
            if (handler != null) {
                return handler;
            }
        }
    }
    return null;
}

아무런 설정을 하지 않아도 DispatcherServlet이 기본적으로 등록한 BeanNameUrlHandlerMapping, RequestMappingHandlerMapping 두 개의 HandlerMapping이 있다. 실질적으로 RequestMappingHandlerMapping이 애노테이션으로 등록한 컨트롤러와 @RequestMapping, @GetMapping, @PostMapping 등을 사용해 지정한 핸들러를 찾아준다.

그 다음에는 HandlerApapter를 찾는다.

doDispatch -> HandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler());

protected HandlerAdapter getHandlerAdapter(Object handler) throws ServletException {
    if (this.handlerAdapters != null) {
        for (HandlerAdapter adapter : this.handlerAdapters) {
            if (adapter.supports(handler)) {
                return adapter;
            }
        }
    }
    throw new ServletException("No adapter for handler [" + handler +
		"]: The DispatcherServlet configuration needs to include a HandlerAdapter that supports this handler");
}

아무런 설정을 하지 않아도 DispatcherServlet이 기본적으로 등록한 기본 전략인 HttpRequestHandlerAdpater, SimpleControllerHandlerAdpater, RequestMappingHandlerAdapter 세 개의 HandlerAdpater가 있다. 그리고 실질적으로 RequestMappingHandlerAdapter가 핸들러를 실행시키는 HandlerAdapter이다.

doDispatch -> mv = ha.handle(processedRequest, response, mappedHandler.getHandler());

HandlerAdpater를 가져와 요청을 처리한다.

ha.handle(processedRequest, response, mappedHandler.getHandler()); -> RequestMappingHandlerAdpater.class -> handleInternal 메소드 -> mav = invokeHandlerMethod(request, response, handlerMethod); 에서 실제 HandlerMethod를 invoke한다.

그리고 @RestController는 @Controller + @ResponseBody이다. 따라서 응답을 처리할 HandleMethodReturnValueHandler는 RequestResponseBodyMethodProcessor가 된다.

참고

  • 인프런 : 스프링 웹 MVC(백기선)
profile
이것저것 관심많은 개발자.

0개의 댓글