Spring MVC 기본 동작 흐름
- Database를 제외한 파란색 부분들은 Spring MVC가 제공한다.
- 요청을 보내면 모든 요청을 Dispatcher Servlet이라고 하는 서블릿 클래스가 받는다.
- Dispatcher Servlet은 요청을 처리해줄 컨트롤러와 메서드가 무엇인지 Handler Mapping에게 물어보고 해당되는 정보를 알아낸다.
- 개발할 때 어떤 요청에 어떤 컨트롤러가 동작할지를 xml 파일이나 java 파일에 어노테이션으로 설정한다.
- 이런 정보들을 Spring으로 만들어진 웹 애플리케이션이 실행할 때 Handler Mapping 객체들이 생성이 되면서 관리를 한다.
- Dispatcher Servlet은 결정된 컨트롤러와 해당 메서드를 실행하기 위해 Handler Adapter에게 실행을 요청한다.
- 그 결과를 Model에 받아서 Dispatcher Servlet에게 전달한다. 이때 컨트롤러는 view name도 리턴한다.
- 컨트롤러가 리턴한 view name을 가지고 적절한 View Resolver를 통해 뷰를 출력한다.
- View Resolver가 어떤 View이다는 정보를 정확하게 알려주면 이 View로 응답을 한다.
DispatcherServlet
- 프론트 컨트롤러이다. 보통 한 개만 선언해서 사용한다.
- 클라이언트의 모든 요청을 받은 후 이를 처리할 핸들러에게 넘기고, 핸들러가 처리한 결과를 받아 사용자에게 응답 결과를 보여준다.
요청 선처리 작업
Locale 결정
- Spring MVC는 지역화라는 것을 지원한다.
- 지역화란 같은 사이트더라도 사용자에 따라 특정 언어로 보여지는 것이다.
- 브라우저가 보내는 헤더 정보에서 언어 설정의 값들을 이용해서 locale을 결정할 수 있다.
RequestContextHolder 요청 저장
- 이 부분은 스레드 로컬 객체이다.
- 요청을 받아서 응답할 때 까지 HttpServletRequest, HttpServletResponse 등을 Spring이 관리하는 객체 안에서 사용할 수 있도록 해주는 이런 것들을 말한다.
- 컨트롤러가 가진 메서드 안에서 Request 객체가 필요하다면, 인자에 HttpServletRequest request 선언만 해주면 된다. 다만, Spring이 웹 기술에 종속되는 문제점이 존재한다.
FlashMap 복원
- Spring 3에서 추가된 기능이다.
- FlashMap은 Redirect로 값을 전달할 때 사용된다.
- redirect로 값을 전달할 때 ?키=값 이런 것을 이용하는데, URL이 복잡해지는 문제점이 있다. URL 길이에 대한 제한도 있다.
- 이런 부분들 때문에 FlashMap을 지원한다. 사용하면 redirect될 때 딱 한번 값을 유지할 수 있게 해준다.
- 즉, FlashMap을 복원한다는 것은 현재 실행이 redirect 되었을 때만 실행이 되는 부분들을 위해 제공하는 것이다.
멀티파트 요청
- 사용자가 파일 업로드를 했을 경우에 HttpServletRequest가 아닌 파일 정보를 읽어들이는 특수한 형태의 Request 객체가 필요하다.
- 이때 멀티파트 요청이 들어오면 MultipartResolver가 Request를 결정하게 해준다.
핸들러 결정과 실행
- 실제 요청을 처리하는 핸들러를 결정하고 실행을 하는 역할까지 해주는 것이 선처리 작업이 하는 일이다.
요청 선처리 작업시 사용된 컴포넌트
org.springframework.web.servlet.LocaleResolver
- 지역 정보를 결정해주는 전략 오브젝트이다.
- 디폴트인 AcceptHeaderLocalResolver는 HTTP 헤더의 정보를 보고 지역정보를 설정해준다.
org.springframework.web.servlet.FlashMapManager
- FlashMap객체를 조회(retrieve) & 저장을 위한 인터페이스
- RedirectAttributes의 addFlashAttribute메소드를 이용해서 저장한다.
- 리다이렉트 후 조회를 하면 바로 정보는 삭제된다.
org.springframework.web.context.request.RequestContextHolder
- 일반 빈에서 HttpServletRequest, HttpServletResponse, HttpSession 등을 사용할 수 있도록 한다.
- 해당 객체를 일반 빈에서 사용하게 되면, Web에 종속적이 될 수 있다.
org.springframework.web.multipart.MultipartResolver
요청 전달
- HandlerMapping으로 HandlerExcecutionChain이 결정된다.
- 해당 Chain을 발견 못하면 Http404를 전달하고, 존재하면 HandlerAdapter가 결정된다.
- 400번대 에러는 없는 페이지를 요청했을 때 발생한다.
- 결정된 HandlerAdapter가 없다면 서버 잘못이기에 ServletException이 발생한다. 문제없이 처리가 됐다면 요청이 잘 처리된다.
요청 전달시 사용된 컴포넌트
org.springframework.web.servlet.HandlerMapping
- HandlerMapping구현체는 어떤 핸들러가 요청을 처리할지에 대한 정보를 알고 있다.
- 디폴트로 설정되는 있는 핸들러 매핑은 BeanNameHandlerMapping과 DefaultAnnotationHandlerMapping 2가지가 설정되어 있다.
org.springframework.web.servlet.HandlerExecutionChain
- HandlerExecutionChain구현체는 실제로 호출된 핸들러에 대한 참조를 가지고 있다.
- 즉, 무엇이 실행되어야 될지 알고 있는 객체라고 말할 수 있으며, 핸들러 실행전과 실행후에 수행될 HandlerInterceptor도 참조하고 있다.
org.springframework.web.servlet.HandlerAdapter
- 실제 핸들러를 실행하는 역할을 담당한다.
- 핸들러 어댑터는 선택된 핸들러를 실행하는 방법과 응답을 ModelAndView로 변화하는 방법에 대해 알고 있다.
- 디폴트로 설정되어 있는 핸들러어댑터는 HttpRequestHandlerAdapter, SimpleControllerHandlerAdapter, AnnotationMethodHanlderAdapter 3가지이다.
- @RequestMapping과 @Controller 애노테이션을 통해 정의되는 컨트롤러의 경우 DefaultAnnotationHandlerMapping에 의해 핸들러가 결정되고, 그에 대응되는 AnnotationMethodHandlerAdapter에 의해 호출이 일어난다.
요청 처리
- 인터셉터는 일종의 필터라고 보면 된다. 이후 챕터에서 다룬다.
- 이전에 실습에서는 서블릿에서 모델을 얻고 그 모델을 JSP로 넘길 때 Request같은 객체를 이용했었다. Spring에서는 종속되지 않기 위해서 Request 대신 ModelAndView를 사용한다.
요청 처리시 사용된 컴포넌트
org.springframework.web.servlet.ModelAndView
- ModelAndView는 Controller의 처리 결과를 보여줄 view와 view에서 사용할 값을 전달하는 클래스이다.
org.springframework.web.servlet.RequestToViewNameTranslator
- 컨트롤러에서 뷰 이름이나 뷰 오브젝트를 제공해주지 않았을 경우 URL과 같은 요청정보를 참고해서 자동으로 뷰 이름을 생성해주는 전략 오브젝트이다. 디폴트는 DefaultRequestToViewNameTranslator이다.
예외 처리
예외 처리시 사용된 컴포넌트
org.springframework.web.servlet.handlerexceptionresolver
- 기본적으로 DispatcherServlet이 DefaultHandlerExceptionResolver를 등록한다.
- HandlerExceptionResolver는 예외가 던져졌을 때 어떤 핸들러를 실행할 것인지에 대한 정보를 제공한다.
뷰 렌더링
뷰 렌더링 과정시 사용된 컴포넌트
org.springframework.web.servlet.ViewResolver
- 컨트롤러가 리턴한 뷰 이름을 참고해서 적절한 뷰 오브젝트를 찾아주는 로직을 가진 전략 오프젝트이다.
- 뷰의 종류에 따라 적절한 뷰 리졸버를 추가로 설정해줄 수 있다.
요청 처리 종료