스프링 MVC 1편 - 백엔드 웹 개발 핵심 기술 /인프런 강의/ 김영한
5.스프링 MVC- 구조 이해 - 스프링 MVC 전체 구조
5.스프링 MVC- 구조 이해 - 핸들러 매핑과 핸들러 어댑터
5.스프링 MVC- 구조 이해 - 뷰 리졸버
관련코드
https://github.com/sunghoonking/spring-mvc-inflearn/tree/main/src/main/java/hello/servlet/web
직접 만든 프레임워크 스프링 MVC 비교
- FrontController -> DispatcherServlet
- handlerMappingMap -> HandlerMapping
- MyHandlerAdapter -> HandlerAdapter
- ModelView -> ModelAndView
- viewResolver -> ViewResolver
- MyView -> View
가장 앞단에서 HTTP 프로토콜로 들어오는 모든 요청을 가장 먼저 받아 적합한 컨트롤러에 위임해주는 프론트 컨트롤러(Front Controller)
protected void doDispatch(HttpServletRequest request, HttpServletResponse
response) throws Exception {
HttpServletRequest processedRequest = request;
HandlerExecutionChain mappedHandler = null;
ModelAndView mv = null;
// 1. 핸들러 조회
mappedHandler = getHandler(processedRequest);
if (mappedHandler == null) {
noHandlerFound(processedRequest, response);
return;
}
// 2. 핸들러 어댑터 조회 - 핸들러를 처리할 수 있는 어댑터
HandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler());
// 3. 핸들러 어댑터 실행 -> 4. 핸들러 어댑터를 통해 핸들러 실행 -> 5. ModelAndView 반환
mv = ha.handle(processedRequest, response, mappedHandler.getHandler());
processDispatchResult(processedRequest, response, mappedHandler, mv,
dispatchException);
}
private void processDispatchResult(HttpServletRequest request,
HttpServletResponse response, HandlerExecutionChain mappedHandler, ModelAndView
mv, Exception exception) throws Exception {
// 뷰 렌더링 호출
render(mv, request, response);
}
protected void render(ModelAndView mv, HttpServletRequest request,
HttpServletResponse response) throws Exception {
View view;
String viewName = mv.getViewName();
// 6. 뷰 리졸버를 통해서 뷰 찾기, 7. View 반환
view = resolveViewName(viewName, mv.getModelInternal(), locale, request);
// 8. 뷰 렌더링
view.render(mv.getModelInternal(), request, response);
}
SpringMVC 구조 및 동작 순서
인터페이스 살펴보기
- 스프링 MVC의 큰 강점은 DispatcherServlet 코드의 변경 없이, 원하는 기능을 변경하거나 확장할 수
있다는 점이다. 지금까지 설명한 대부분을 확장 가능할 수 있게 인터페이스로 제공한다.
- 이 인터페이스들만 구현해서 DispatcherServlet 에 등록하면 여러분만의 컨트롤러를 만들 수도 있다
핸들러 매핑
Dispatcher Servlet이 요청 URI가 어떤 핸들러와 매핑되는지 찾는 과정이다. 핸들러 매핑은 결국 요청과 알맞는 핸들러 객체를 Dispatcher Servlet에 리턴한다.
핸들러 어댑터
HandlerMapping을 통해 찾은 컨트롤러를 직접 실행하는 기능을 수행
스프링도 처음에는 이런 딱딱한 형식의 컨트롤러를 제공했다.
HandlerMapping
0 = RequestMappingHandlerMapping:
애노테이션 기반의 컨트롤러인 @RequestMapping에서 사용
1 = BeanNameUrlHandlerMapping :
스프링 빈의 이름으로 핸들러를 찾는다.HandlerAdapter
0 = RequestMappingHandlerAdapter :
애노테이션 기반의 컨트롤러텍스트인 @RequestMapping에서 사용
1 = HttpRequestHandlerAdapter :
HttpRequestHandler 처리
2 = SimpleControllerHandlerAdapter :
Controller 인터페이스(애노테이션X, 과거에 사용) 처리
1. 핸들러 매핑으로 핸들러 조회
2. 핸들러 어댑터 조회
3. 핸들러 어댑터 실행
정리 - OldController 핸들러매핑, 어댑터
OldController 를 실행하면서 사용된 객체는 다음과 같다.
HandlerMapping = BeanNameUrlHandlerMapping
HandlerAdapter = SimpleControllerHandlerAdapter
스프링 부트가 자동 등록하는 뷰 리졸버
1 = BeanNameViewResolver :
빈 이름으로 뷰를 찾아서 반환한다. (예: 엑셀 파일 생성 기능에 사용)
2 = InternalResourceViewResolver :
JSP를 처리할 수 있는 뷰를 반환한다
1. 핸들러 어댑터 호출
핸들러 어댑터를 통해new-form
이라는 논리 뷰 이름을 획득한다.2. ViewResolver 호출
new-form
이라는 뷰 이름으로 viewResolver를 순서대로 호출한다.
BeanNameViewResolver
는new-form
이라는 이름의 스프링 빈으로 등록된 뷰를 찾아야 하는데 없다.
InternalResourceViewResolver
가 호출된다.3. InternalResourceViewResolver
이 뷰 리졸버는InternalResourceView
를 반환한다.4. 뷰 - InternalResourceView
InternalResourceView
는 JSP처럼 포워드forward()
를 호출해서 처리할 수 있는 경우에 사용한다.5. view.render()
view.render()
가 호출되고InternalResourceView
는forward()
를 사용해서 JSP를 실행한