1. DispatcherServlet
- Spring WEB MVC는 FrontController 패턴을 사용한다. 이때 FrontController역할을 하는 객체가 DispatcherServlet이다.
- DispatcherServlet은 Servlet을 상속하며 모든 웹 요청에서 가장 먼저 수행된다.
- 내가 생각하는 Spring Web MVC의 핵심 키워드 로직은 아래와 같다.
- 핸들러 매핑 : 요청한 URL에 맞는 핸들러(컨트롤러)를 찾는 과정
- 핸들러 어댑터 : 다양한 형태의 핸들러(컨트롤러)를 일관된 방식으로 FrontController에서 호출할 수 있게 지원하는 객체
- 핸들러(컨트롤러) : 사용자 요청을 비즈니스 로직으로 연결하는 객체(실제 내가 구현한 controller 코드)
- 뷰 리졸버 : 컨트롤러가 반환한 view의 논리적인 이름을 실제 경로로 연결하고 view를 템플릿 엔진에 연결하는 객체
- 인터셉터 : 컨트롤러 수행전/후/완료 후 실행되는 객체
- 익셉션 핸들러 : controller아래에서 발생한 에러에 대한 처리를 지원하는 객체
2. 추상화된 호출 메소드 순서
|doDispatch()
--> |mappedHandler = getHandler(processedRequest);
--> |HandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler());
--> |mappedHandler.applyPreHandle(processedRequest, response)
--> |mv = ha.handle(processedRequest, response, mappedHandler.getHandler());
--> |mappedHandler.applyPostHandle(processedRequest, response, mv);
--> |processDispatchResult(processedRequest, response, mappedHandler, mv, dispatchException);
--> |mv = processHandlerException(request, response, handler, exception);
--> |render(mv, request, response);
--> |view = resolveViewName(viewName, mv.getModelInternal(), locale, request);
--> |view.render(mv.getModelInternal(), request, response);
--> |mappedHandler.triggerAfterCompletion(request, response, null);
- 메소드 호출 순서를 인터셉터의 수행시점을 이해할 수 있다.
- applyPostHandle의 경우 controller 수행 간 예외 발생시(ha.handle()) catch문으로 넘어가기 때문에 실행되지 않는다. 반면 afterCompletion의 경우 processDispatchResult()내부 또는 finally에서 실행되기 때문에 예외 발생과 상관없이 무조건 실행된다.
3. HandlerMapping 구조
- DispatcherServlet에는 아래와 같은 변수가 있다.
private List<HandlerMapping> handlerMappings
- 해당 변수를 실행 과정에서 디버깅 해보면
{RequestMappingHandlerMapping, BeanNameUrlHandlerMapping, RouterFunctionMapping, SimpleUrlHandlerMapping, WelcomPagehandlerMapping}
이 할당되어 있다.
- 일반적으로는 HandlerMethod를 쓰게되는데, 이는
RequestMappingHanlerMapping
이 처리한다.
- RequestmappingHandlerMapping : @RequestMapping 컨트롤러 매핑
-> RequestmappingHandlerMapping이 처리
- BeanNameUrlHandlerMapping : 스프링 빈의 이름으로 핸들러 매핑
-> SimpleControllerHandlerAdapter가 처리
RequestMappingHanlerMapping
내부를 보면 AbstracHandlerMehtodMapping.MappingRegistry mappingRegistry
가 선언되어 있고, registry에는 URL과 해당하는 handlerMethod(AbstractHandlerMethodMapping~)가 key:value형태로 등록되어 있다.