티스토리 뷰

Spring MVC의 요청 흐름을 아래의 그림으로 요약할 수 있고, 중간에 중요한 개념들을 정리하려고 한다.


DispatcherServlet

  • 프론트 컨트롤러 패턴을 구현할 실체이다.
  • 클라이언트의 모든 Request를 접수하고, 다른 컴포넌트에 역할을 위임한다.
  • 주로 HandlerMapping, HandlerAdapter, ViewResolver로 역할을 위임한다.

HandlerMapping

특징

  • Request의 URL과 매칭 되는 Handler를 선택한다.
  • HandlerMapping 인터페이스를 구현한 여러 구현체들이 있고, 구현체들의 우선순위를 기준으로 매칭 되는 Handler를 선택한다.
  • 여러 구현체들이 있지만, 대표적으로 RequestMappingHandlerMapping과 BeanNameUrlHandlerMapping이 있다.
RequestMappingHandlerMapping
  • @RequestMapping과 같은 Annotation 기반의 Handler를 찾는다.
  • 우선순위는 0으로 가장 높다.
BeanNameUrlHandlerMapping
  • Spring Bean의 이름으로 Handler를 찾는다.
  • 우선순위는 1이다.

동작 방식

DispatcherServlet 클래스 doService()의 doDispatch() 메서드가 실행되고, getHandler() 메서드에 의해 Handler를 찾는다. 이때, HandlerMapping을 구현한 구현체의 우선순위에 따라 찾게 된다.

DispatcherServlet 클래스의 doService()
@Override
protected void doService(HttpServletRequest request, HttpServletResponse response) throws Exception {
    // 생략...
    try {
    
    	doDispatch(request, response);
        
    } finally {
    	// 생략...
    }
    // 생략...
}
DispatcherServlet 클래스의 doDispatch()
protected void doDispatch(HttpServletRequest request, HttpServletResponse response) throws Exception {
	// 생략...
    try {
   		
    	mappedHandler = getHandler(processedRequest);
        
    } catch () {
    	// 생략
    }
    // 생략...
}
DispatcherServlet 클래스의 getHandler()
@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;
}

HandlerAdapter

특징

  • DispatcherServlet에서 보낸 HttpServletRequest, HttpServletResponse 객체를 전달받고, 내부 로직에서 Controller를 실행한다.
  • HandlerAdapter 인터페이스의 구현체들이 존재하고, 대표적으로 RequestMappingHandlerAdapter, HttpRequestHandlerAdapter, SimpleControllerHandlerAdapter가 있다.
RequestMappingHandlerAdapter
  • Annotation 기반의 Controller에서 사용한다.
  • 우선순위는 0
HttpRequestHandlerAdapter
  • Http 형식을 처리한다.
  • 우선순위는 1
SimpleControllerHandlerAdapter
  • Controller 인터페이스를 구현한 클래스가 사용한다.
  • 과거에 사용했으며, 현재는 잘 사용하지 않는다.
  • 우선순위는 2

동작 방식

DispatcherServlet에서 getHandler() 메서드를 통해 Handler를 가져오고, getHandlerAdapter() 메서드를 통해 HandlerAdapter를 찾은 다음에 handle() 메서드에 의해 요청이 처리된다.

DispatcherServlet 클래스의 doDispatch()
protected void doDispatch(HttpServletRequest request, HttpServletResponse response) throws Exception {
	// 생략...
    try {
   		
        // Handler 조회
    	mappedHandler = getHandler(processedRequest);
        
        // HandlerAdapter 조회
        HandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler());
        
        // HandlerAdpater의 handle() 실행을 통해 Controller로 요청한다.
        mv = ha.handle(processedRequest, response, mappedHandler.getHandler());
        
    } catch () {
    	// 생략
    }
    // 생략...
}
DispatcherServlet 클래스의 getHandlerAdapter()
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");
}

HandlerAdapter를 구현한 클래스는 AbstractHandlerMethodAdapter가 있으며, handle() 메서드 내부의 handlerInternal() 메서드에 의해서 처리된다.

AbstractHandlerMethodAdapter 클래스의 handle()
@Override
@Nullable
public final ModelAndView handle(HttpServletRequest request, HttpServletResponse response, Object handler)
        throws Exception {
    return handleInternal(request, response, (HandlerMethod) handler);
}
AbstractHandlerMethodAdapter 클래스의 handlerInternal()
// 하위 클래스에서 override 해야함
@Nullable
protected abstract ModelAndView handleInternal(HttpServletRequest request,
		HttpServletResponse response, HandlerMethod handlerMethod) throws Exception;

대표적으로 자주 사용되는 HandlerAdapter 구현체 중에서 RequestMappingHandlerAdapter가 있는데, handleInternal() 메서드 내부에서 checkRequest() 메서드를 통해 HttpServletRequest를 검증하고, invokeHandlerMethod() 메서드에 의해서 Controller로 요청을 보내게 된다.

RequestMappingHandlerAdapter 클래스의 handlerInternal()
@Nullable
protected abstract ModelAndView handleInternal(HttpServletRequest request,
		HttpServletResponse response, HandlerMethod handlerMethod) throws Exception {

    // Request 검증
    checkRequest(request);
    
    // 조건에 따라 invokeHandlerMethod()를 호출한다. 직접 코드를 확인할 것
    mav = invokeHandlerMethod(request, response, handlerMethod);
}
RequestMappingHandlerAdapter 클래스의 invokeHandlerMethod()
@Nullable
protected ModelAndView invokeHandlerMethod(HttpServletRequest request,
		HttpServletResponse response, HandlerMethod handlerMethod) throws Exception {

    // 생략...
    try {
        // 생략...
    }
    finally {
        // 생략...
    }
}

invokeHandlerMethod() 메서드 내부에는 HandlerMethodArgumentResovlers를 통해 HttpServlet, Model, @RequestParam, @ModelAttribute, @RequestBody, HttpEntity와 같은 부분들을 유연하게 처리하는 로직이 있으며, HandlerMethodReturnValueHandler를 통해 @ResponseBody, HttpEntity를 처리하는 로직이 존재하며, 기타 로직들을 수행하여, 사용자의 요청을 Controller로 전달한다.


참고

https://www.inflearn.com/course/%EC%8A%A4%ED%94%84%EB%A7%81-mvc-1

스프링 MVC 1편  - 백엔드 웹 개발 핵심 기술 - 인프런 | 강의

웹 애플리케이션을 개발할 때 필요한 모든 웹 기술을 기초부터 이해하고, 완성할 수 있습니다. 스프링 MVC의 핵심 원리와 구조를 이해하고, 더 깊이있는 백엔드 개발자로 성장할 수 있습니다., -

www.inflearn.com

https://velog.io/@hsw0194/Spring-MVC-HandlerMapping%EC%9D%98-%EB%8F%99%EC%9E%91%EB%B0%A9%EC%8B%9D-%EC%9D%B4%ED%95%B4%ED%95%98%EA%B8%B0-1%ED%8E%B8

Spring MVC - HandlerMapping의 동작방식 이해하기 1편

HandlerMapping은 어떻게 동작할까? request에 맞는 handler만 어떻게 가져올 수 있을까?

velog.io

https://velog.io/@jihoson94/Spring-MVC-HandlerAdapter-%EB%B6%84%EC%84%9D%ED%95%98%EA%B8%B0

Spring MVC HandlerAdapter 분석하기

DispatcherServlet을 분석하면서 추상적으로 어떤 역할들을 하는지 살펴봤었습니다. 이번에는 구체적인 HandlerAdapter들을 살펴보고 각각의 차이점을 살펴보겠습니다.Request 분석(Locale, Theme, Multipart 등

velog.io

댓글
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
TAG
more
«   2024/05   »
1 2 3 4
5 6 7 8 9 10 11
12 13 14 15 16 17 18
19 20 21 22 23 24 25
26 27 28 29 30 31
글 보관함