1. DispatcherServlet이란?
Controller의 공통 부분인 입력을 따로 빼낸 것이 DispatcherServlet이다. DispatcherServlet은 전처리이다. 각 서블릿이 공통적으로 처리해야 할 일을 해주는 것이 전처리라 생각하자.
2. Spring MVC의 요청 처리 과정
DispatcherServlet이 요청을 받고 Controller에게 요청의 결과로 view 이름을 받고, 이에 해당하는 jsp를 찾아 응답을 해주는 것이 MVC 요청 처리 과정이다. 하지만 중간에 생략된 것이 있다.
HandlerMapping에 Key는 URL, Value는 메서드 형태로 mapping되어 있다. 요청으로 "ch2/register/add"가 들어오면 HandlerMapping이 URL에 해당하는 메서드를 찾아서 DispatcherServlet에게 전달한다. DispatcherServlet은 이에 해당하는 메서드를 호출한다. 관심사의 분리 첫 번째로 입력을 DispatcherServlet으로 분리시켰고 또 역할을 나눠 HandlerMapping으로 분리시켰다 생각하면 된다.
DispatcherServlet과 Controller 사이에도 원래 HandlerAdapter가 들어간다. DispatcherServlet가 메서드를 직접 호출하지 않고 HandlerAdapter를 거쳐서 호출한다. HandlerAdapter의 종류가 1개 이상일 수 있어서 다른 종류의 객체를 호출할 수 있게돼있다. HandlerMapping에게 받은 메서드를 보고 이에 맞는 HandlerAdapter에게 넘겨준다. 그 다음 HandlerAdapter가 해당 Controller에게 요청을 전달한다.
가운데 HandlerAdapter를 둬 느슨한 연결이 되었다. 따라서 변경에 유리한 장점이 있다. 만약 직접 호출하게 되면 해당 Controller가 아닌 다른 객체를 호출해야 할 때 DispatcherServlet의 내용을 수정해야한다. HandlerAdapter이 있으면 내용을 수정하지 않고 다른 HandlerAdapter에게 연결만 하면 다른 객체를 호출할 수 있어 유연하고 변경에 좋다. DispatcherServlet이 메서드 말고도 서블릿을 호출할 수 있다.
ViewResolver가 있는데 InternalResourceViewResolver가 기본이고 지금까지 이것을 사용했다.
servlet-context를 보면 InternalResourceViewResolver가 있고 view 이름을 받으면 접미사, 접두사를 붙여 실제 view 이름을 만들어준다.
Controller가 "registerForm" 이름을 반환하면 DispatcherServlet이 이를 ViewResolver에게 전달한다. 다음 ViewResolver는 "/WEB-INF/views/registerForm.jsp"를 만들어 DispatcherServlet에게 반환한다. DispatcherServlet이 이를 Model과 같이 전달하고 registerForm.jsp는 Model에 들어있는 데이터를 이용해 페이지를 완성하고 클라이언트에게 응답을 한다.
실제로 DispatcherServlet과 View 사이에 View인터페이스가 있다. jsp파일의 인터페이스는 JstlView이다. HandlerAdapter와 마찬가지로 느슨하게 연결돼 변경에 유리한 장점이 있다.
3. DispatcherServlet의 소스 분석
DispatcherServlet.class spring-webmvc-5.0.7.RELEASE.jar에서 5.0.7은 스프링 버전으로 다를 수 있다. 소스 파일 위치는 org/springframework/web/servlet/DispatcherServlet.java 이고 DispatcherServlet.properties은 기본 전략이다. DispatcherServlet이 사용자의 요청을 처리하기 위해 사용하는 클래스가 있다. 종류는 여러개이고 설정을 통해 바꿀 수도 있다. 기본 전략은 사용할 것들이 이미 정해져 있고 DispatcherServlet.properties에 들어 있다. 전략이라는 말이 어려울 수 있는데 전략 패턴이라는 객체지향 디자인에서 따온 말이다.
실습
Maven Dependencies 하위 항목에 org.springframework.web.servlet가 있다.
등호 표시 구분자로 key와 value가 연결되어 있다. key는 DispatcherServlet이 기본적으로 사용하는 전략이 적혀있고 그 전략에 어떤 클래스가 사용될지 적혀있다. LocaleResolver전략에는 AcceptHeaderLocaleResolver를 사용한다.
HandlerMapping은 BeanNameUrlHandlerMapping, RequestMappingHandlerMapping 2개가 사용된다. 순서가 있어서 앞에서 부터 찾으며 없으면 2번째로 넘어간다.
HandlerAdapter는 여러개가 등록되어 있다. DispatcherServlet가 요청하는 객체가 꼭 Controller만 있는 건 아니다. 따라서 기본적으로 여러개가 있다.
HandlerExceptionResolver는 예외처리에 사용한다.
ViewResolver는 실제 view 이름을 반환하는데 이 때, InternalResourceViewResolver를 사용한다. FlashMapManager는 데이터를 일시적으로 Map 형태로 저장하는 기능이 있다. 세션을 사용해서 기본 전략이 SessionFlashMapManager로 되어 있다.
LoginController를 Debug모드로 실행한다.
호출 스택을 보면 톰캣이 요청을 받아서 DispatcherServlet에게 넘기고 DispatcherServlet이 service를 호출한다. service는 servlet 공부할 때 main 메서드 같은 것이라고 배웠었다.
Get 요청이므로 doGet을 호출하고 do.service -> do.Dispatch 순으로 호출한다. 이에 대해서 나중에 배운다.
HandlerAdapter에 여러개가 등록되어 있었는데 그 중에 RequestMappingHandlerAdapter를 사용한다. URL에 연결할 때 RequestMapping 어노테이션을 사용했기 때문에
Method가 실제로 실행되는 것은 LoginController의 loginForm 메서드이다. Method정보가 안나와서 그냥 Method라 써져있다.
RequestMappingHandlerMapping은 RequestMapping 어노테이션이 붙은 모든 메서드를 map 형태로 저장한다. "/ex2"는 ExceptionController클래스의 main2 메서드와 연결돼있다. 서버가 시작되면서 이런 key, value 형태로 mapping이 저장된다. 만약 검색했는데 나오지 않는다면 mapping이 안되었다는 뜻이다.
DispatcherServlet도 서블릿 이므로 service부터 시작한다. HttpServletresponse로부터 응답을 받아서 Get 요청이면 doGet을 실행한다. doService는 딱히 하는일은 없고 do.Dispatch를 실행한다.
doDispatch를 보면 processedRequest 요청과 연결된 Handler 메서드를 가져온다.
HandlerMapping에게 URL에 연결되 있는 메서드를 물어보면 HandlerMethod를 반환한다. HandlerMapping에는 URL과 메서드가 쌍으로 mapping돼있으며 HandlerMethod에는 메서드 정보가 담겨있다. DispatcherServlet은 여러개의 HandlerAdapter에서 메서드를 처리할 수 있는 HandlerAdapter에게 요청한다.
HandlerAdapter에게 처리할 수 있는 Method를 가져오면 실제 처리는 ha.handle이 메서드를 호출한다. 결과 mv는 Model and View이고 메서드 호출을 결과 mv에 담아서 반환한다.
밑으로 내려가면 PostHandle이 있는데 Intercept이다.
Servlet에서 요청과 응답을 filter를 통해 전처리, 후처리 한다. Intercept는 filter의 발전된 형태이다.
processDispatchResult가 메서드 호출 결과 mv를 받는다.
doDispatcher를 보면 DispatchServlet에서 사용할 변수들이 instance 변수로 선언되어 있다. DispatchServlet.propeties 파일을 읽어서 여기에 저장하기 때문이다. List로 되어 있는 HandlerAdapter는 순서가 있어 순서대로 찾는다는 말이다.
'스프링의 정석 > Ch. 02 Spring MVC' 카테고리의 다른 글
32. IntelliJ 설치 - Windows (0) | 2023.08.23 |
---|---|
30. 데이터의 변환과 검증(1) (0) | 2023.08.18 |
27. 예외처리(1) - 실습 (0) | 2023.08.16 |
26. 세션(Session) - 실습(2) (0) | 2023.08.15 |
25. 세션(Session) - 실습(1) (0) | 2023.08.14 |