DispatcherServlet
: Spring의 프론트 컨트롤러View
: 인터페이스로 구성되어 있다, 확장성을 가지고 있다.(urlPatterns=”/”)
FrameworkServlet.service()
를 시작으로 여러 메서드가 호출됨과 동시에 가장 중요한DispatcherServlet.doDispatch()
가 호출된다.protected void doDispatch() {
...
// 1. 핸들러 조회
mappedHandler = getHandler(processedRequest);
if (mappedHandler == null) {
noHandlerFound(processedRequest, response); // NotFound 404
}
// 2. 핸들러 어댑터 조회 : 핸들러를 처리할 수 있는 어댑터
HandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler());
// 3. 핸들러 어댑터 실행
// 4. 핸들러 어댑터를 통해 핸들러 실행
// 5. ModelAndView 반환
mv = ha.handle(processedRequest, response, mappedHandler.getHandler());
// 여기 안에서 render
processDispatchResult(processedRequest, response, mappedHandler, mv,dispatchException);
...
}
// processDispatchResult()
private void processDispatchResult(HttpServletRequest request, HttpServletResponse response,
@Nullable HandlerExecutionChain mappedHandler, @Nullable ModelAndView mv,
@Nullable Exception exception) throws Exception {
if (mv != null && !mv.wasCleared()) {
// View Render 호출
render(mv, request, response);
if (errorView) {
WebUtils.clearErrorRequestAttributes(request);
}
}
}
// render()
protected void render(ModelAndView mv, HttpServletRequest request, HttpServletResponse response) throws Exception {
View view;
String viewName = mv.getViewName();
// 6. ViewResolver를 통해 View 조회
// 7. View 반환
view = resolveViewName(viewName, mv.getModelInternal(), locale, request);
// 8. View Rendering
view.render(mv.getModelInternal(), request, response);
}
Spring MVC는 DispatcherServlet 코드의 변경 없이 기능변경 및 확장이 가능하다. 기능들이 대부분 Interface로 만들어져 있기 때문이다.
-> 인터페이스를 implements 하여 구현하면 내가 만든 클래스를 사용할 수 있다. (객체지향의 다형성)
org.springframework.web.servlet
-> 구성 요소들을 다 알필요는 없지만 파악은 해놓기!
1. Handler Mapping
- 핸들러 매핑에서 ExampleController를 찾을 수 있어야 한다.
→ Spring Bean의 이름으로 핸들러를 찾을 수 있는 핸들러 매핑이 필요하다.
2. Handler Adapter
- Handler Mapping을 통해 찾은 핸들러를 실행할 수 있는 Handler Adapter가 필요
→ Controller Interface를 실행할 수 있는 Handler Adapter를 찾고 실행한다.
- **HandlerMapping**
- 우선순위 순서
1. **RequestMappingHandlerMapping**
- 우선순위가 가장 높다
- Annotation 기반 Controller의 `@RequestMapping`에 사용
2. BeanNameUrlHandlerMapping(위 예시코드에 사용)
- Spring Bean Name으로 HandlerMapping
- **HandlerAdapter**
- 우선순위 순서
1. **RequestMappingHandlerAdapter**
- Annotation 기반 Controller의 `@RequestMapping`에서 사용
2. HttpRequestHandlerAdapter
- HttpRequestHandler 처리
3. SimpleControllerHandlerAdapter(위 예시코드에 사용)
- Controller Interface 처리