8. FrameworkServlet → DispatcherServlet: doDispatch()
FrameworkServlet의 상위 기본 처리가 끝나면, DispatcherServlet의 doDispatch()로 실제 Spring MVC 로직이 실행되는 단계를 오픈소스 코드 근거로 분석합니다.
전체 흐름 요약
- FrameworkServlet.service()가 호출 (상위 클래스 기본 처리)
- FrameworkServlet.processRequest()에서 doService()를 호출 (템플릿 메서드 패턴)
- DispatcherServlet.doService()에서 doDispatch() 호출 (하위 클래스 구현)
- doDispatch()에서 핸들러 매핑, 인터셉터, 컨트롤러 호출 등 모든 MVC 로직 실행
실제 코드 흐름 분석
1) FrameworkServlet.service() → processRequest()
// FrameworkServlet.java
@Override
public void service(ServletRequest req, ServletResponse res) throws ServletException, IOException {
HttpServletRequest request = (HttpServletRequest) req;
HttpServletResponse response = (HttpServletResponse) res;
processRequest(request, response);
}
protected final void processRequest(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
...
try {
doService(request, response); // 템플릿 메서드: 하위 클래스에서 구현
}
finally {
...
}
}
2) DispatcherServlet.doService() → doDispatch()
// DispatcherServlet.java
@Override
protected void doService(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
...
try {
doDispatch(request, response); // 실제 MVC 로직 시작
}
finally {
...
}
}
protected void doDispatch(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
HttpServletRequest processedRequest = request;
HandlerExecutionChain mappedHandler = null;
boolean multipartRequestParsed = false;
try {
ModelAndView mv = null;
Exception dispatchException = null;
try {
processedRequest = checkMultipart(request);
multipartRequestParsed = (processedRequest != request);
// 1. 핸들러 매핑
mappedHandler = getHandler(processedRequest);
// 2. 핸들러 어댑터 획득
HandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler());
// 3. 인터셉터 preHandle
if (!mappedHandler.applyPreHandle(processedRequest, response)) {
return;
}
// 4. 컨트롤러 호출
mv = ha.handle(processedRequest, response, mappedHandler.getHandler());
// 5. 인터셉터 postHandle
mappedHandler.applyPostHandle(processedRequest, response, mv);
}
catch (Exception ex) {
dispatchException = ex;
}
// 6. 뷰 렌더링
processDispatchResult(processedRequest, response, mappedHandler, mv, dispatchException);
}
finally {
...
}
}
시퀀스 다이어그램
sequenceDiagram
participant FrameworkServlet
participant DispatcherServlet
participant HandlerMapping
participant Interceptor as HandlerInterceptor
participant Controller
FrameworkServlet->>DispatcherServlet: doService()
DispatcherServlet->>DispatcherServlet: doDispatch()
DispatcherServlet->>HandlerMapping: getHandler()
HandlerMapping-->>DispatcherServlet: HandlerExecutionChain
DispatcherServlet->>Interceptor: preHandle()
DispatcherServlet->>Controller: handle()
Controller-->>DispatcherServlet: ModelAndView
DispatcherServlet->>Interceptor: postHandle()
설계 의도 및 이유
- 템플릿 메서드 패턴: FrameworkServlet은 기본 구조(service → processRequest)를 정하고, DispatcherServlet에서 구체적 구현(doService → doDispatch)을 채움
- 계층 분리: 상위 클래스에서 공통 처리(요청/응답 관리, 트랜잭션 처리)를 하고, 하위 클래스에서 MVC 로직(핸들러 매핑, 컨트롤러 호출)에 집중
- 확장성: 다른 서블릿도 FrameworkServlet을 상속받아 자신의 doService()를 구현 가능
← 이전: 7. StandardWrapperValve → FrameworkServlet | 다음: 9. DispatcherServlet → HandlerMapping