Notice
Recent Posts
Recent Comments
Link
10-09 18:27
관리 메뉴

JingyuKim

Dispatcher Servlet, Handler Method, RequestMappingHandlerMapping 본문

Tech/스프링

Dispatcher Servlet, Handler Method, RequestMappingHandlerMapping

kimjingyu 2023. 2. 13. 15:44

HandlerMethod

  • @RequestMapping 과 그 하위 어노테이션이 붙은 메소드의 정보를 추상화한 객체
  • HandlerMethod 는 그 자체가 실행 가능한 객체가 아니라 메소드를 실행하기 위해 필요한 참조정보를 담고 있는 객체이다.
    • 빈 객체
    • 메소드 메타정보
    • 메소드 파라미터 메타정보
    • 메소드 어노테이션 메타정보
    • 메소드 리턴 값 메타정보
  • DispatcherServlet 은 애플리케이션이 실행될 때 모든 컨트롤러 빈의 메소드를 살펴서 매핑 후보가 되는 메소드들을 추출한 뒤 이를 Handler Method 형태로 저장해둔다.
  • 그리고 실제 요청이 들어오면 저장해 둔 목록에서 요청 조건에 맞는 HandlerMethod 를 참조해서 매핑되는 메소드를 실행한다.

RequestMappingHandlerMapping

  • HTTP 요청을 HandlerMethod 객체로 변환하는 작업
  • 해당 요청에 매핑되는 HandlerMethod 를 반환하는 작업 담당
  • 애플리케이션 컨텍스트가 초기화되면 RequestMappingHandlerMapping 에 접근하여 저장된 매핑 정보와 HandlerMethod 목록을 확인할 수 있다.

DispatcherServlet 이 HTTP 요청을 처리하는 방법

  • 디스패처 서블릿은 적합한 컨트롤러와 메소드를 찾아 요청을 위임해야 한다.
  1. 클라이언트의 요청을 디스패처 서블릿이 받음
    1. 디스패처 서블릿은 프론트 컨트롤러이다.
    2. 서블릿 컨텍스트 ( 웹 컨텍스트 ) 에서 필터들을 지나 스프링 컨텍스트에서 디스패처 서블릿이 가장 먼저 요청을 받게 된다.
  2. 요청 정보를 통해 요청을 위임할 컨트롤러를 찾음 ( Handler Mapping - Handler 조회 )
    1. 디스패처 서블릿은 요청을 처리할 컨트롤러를 찾고 해당 메소드를 호출해야 한다.
    2. HandlerMapping의 구현체 중 하나인 RequestMappingHandlerMapping@Controller로 작성된 모든 컨트롤러 빈을 parsing 하여 HashMap으로 (요청 정보 - 처리할 대상)을 관리한다.
    3. 이 때, 엄밀히 말해서 컨트롤러가 아닌 요청에 매핑되는 컨트롤러해당 메소드 등을 갖는 HandlerMethod 객체를 찾는다.
    4. 따라서 HandlerMapping은 요청이 오면
      1. Http Method, URI 등을 사용해 Key 객체인 요청 정보를 만들고,
      2. Value인 요청을 처리할 HandlerMethod를 찾아 HandlerMethodExecutionChain으로 감싸서 반환한다.
      3. HandlerMethodExecutionChain 으로 감싸는 이유는 컨트롤러로 요청을 넘겨주기 전에 처리해야 하는 Interceptor 등을 포함하기 위해서이다.
  3. 요청을 컨트롤러로 위임할 핸들러 어댑터를 찾아서 전달함 ( Handler Adapter 목록 - 핸들러를 처리할 수 있는 핸들러 어댑터 조회 )
    1. Dispatcher Servlet 은 컨트롤러로 요청을 직접 위임하는 것이 아니라 HandlerAdapter 를 통해 컨트롤러로 요청을 위임한다.
    2. 이때 Adapter Interface 를 통해 컨트롤러를 호출하는 이유는 컨트롤러의 구현 방식이 다양하기 때문이다.
      1. 최근에는 @Controller 에 @RequestMapping 관련 어노테이션을 사용해서 컨트롤러 클래스를 주로 작성하지만
      2. Controller Interface 를 구현하여 컨트롤러 클래스를 작성할 수도 있다.
    3. 즉, 스프링은 HandlerAdapter라는 Adapter Interface 를 통해 어댑터 패턴을 적용함으로써 컨트롤러의 구현 방식에 상관없이 요청을 위임할 수 있다.
    4. HandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler());
  4. 핸들러 어댑터가 컨트롤러로 요청을 위임함
    1. Handler Adapter 가 컨트롤러로 요청을 넘기기 전에 공통적인 전/후 처리 과정이 필요하다.
      1. @RequestParam, @RequestBody 등을 처리하기 위한 ArgumentResolver, HTTP Message Converter
      2. ResponseEntity 의 Body를 JSON 으로 직렬화하는 등의 처리를 하는 ReturnValueHandler 등이 어댑터에서 컨트롤러로 전달되기 전에 처리된다.
      3. 컨트롤러의 메소드를 호출하도록 요청을 위임한다. ( 리플렉션 사용 )
        1. 요청을 처리할 대상 정보인 HandlerMethod 객체에는 컨트롤러 정보와 메소드 객체가 있으므로 리플렉션의 메소드 객체를 invoke 한다.
  5. 비즈니스 로직을 처리함
  6. 컨트롤러가 반환값을 반환함
    1. MSA 로 가고 있는 시대에서는 주로 ResponseEntity를 반환한다.
  7. Handler Adapter 가 반환값을 처리함
  8. 서버의 응답을 클라이언트로 반환함
참조
https://mangkyu.tistory.com/180