-
Spring Doc - Core - Web MVCDocs/Spring 2021. 5. 3. 20:14
Spring framework Document 읽기
- 현재 담당하는 서비스가 Spring5를 사용하진 않지만 5의 문서를 읽으면서 추가된 내용이 아니라 Spring framework 자체의 내용에 집중해볼 예정입니다.
Docs : https://docs.spring.io/spring/docs/5.2.4.RELEASE/spring-framework-reference/web.html#spring-web
Repo : https://github.com/spring-projects/spring-framework
Github repository에서 "T"를 누르면 파일 검색이 가능합니다.
Spring Web MVC
- Spring Web MVC는 Servlet API 기반으로 만들어진 웹 프레임워크 이며 Spring의 시작부터 포함되어 있었습니다.
- Spring 5.0 부터는 Spring WebFlux가 소개되었고 MVC를 대체하여 사용할 수 있습니다.
DispatcherServlet
Spring MVC도 다른 web framework들과 마찬가지로 front controller 패턴을 중심으로 설계되었습니다.
DispatcherServlet
에서 request 처리를 위임 하기 위한 알고리즘을 제공하고 실제 동작 수행은 각 작업에 맞는 컴포넌트에서 수행하게 됩니다.DispatcherServlet
도 다른 servlet과 마찬가지로 web.xml 혹은 java configuration 방식으로 선언 및 맵핑이 필요합니다. 이렇게 설정한 DispatcherServlet은 request mapping, view resolution, exception handling 등에 필요한 컴포넌트를 찾는데 사용합니다.public class MyWebApplicationInitializer implements WebApplicationInitializer { @Override public void onStartup(ServletContext servletCxt) { // Load Spring web application configuration AnnotationConfigWebApplicationContext ac = new AnnotationConfigWebApplicationContext(); ac.register(AppConfig.class); ac.refresh(); // Create and register the DispatcherServlet DispatcherServlet servlet = new DispatcherServlet(ac); ServletRegistration.Dynamic registration = servletCxt.addServlet("app", servlet); registration.setLoadOnStartup(1); registration.addMapping("/app/*"); } }
<web-app> <listener> <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class> </listener> <context-param> <param-name>contextConfigLocation</param-name> <param-value>/WEB-INF/app-context.xml</param-value> </context-param> <servlet> <servlet-name>app</servlet-name> <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> <init-param> <param-name>contextConfigLocation</param-name> <param-value></param-value> </init-param> <load-on-startup>1</load-on-startup> </servlet> <servlet-mapping> <servlet-name>app</servlet-name> <url-pattern>/app/*</url-pattern> </servlet-mapping> </web-app>
Spring boot는 initialization 과정이 다르기 때문에 servlet container의 lifecycle hook을 사용해서 등록하지 않고, Spring configuration을 통해서 embedded servlet container를 부트스트랩 하며 이때 선언된
Filter
와Servlet
도 함께 감지(detect)하여 컨테이너에 등록됩니다.DispatcherServlet
의 설정을 위해서WebApplicationContext
가 사용됩니다.WebApplicationContext
는ServletContext
와 연관된Servlet
에 대한 링크를 가지고 있으며ServletContext
에 바인딩 되어 있기 때문에 어플리케이션에서WebApplicationContext
에 접근이 필요한 경우RequestContextUtils
의 static 메서드를 통해 접근할 수 있습니다.
Special Bean Types
DispatcherServlet
은 request를 처리하기 위해 특별한 bean들에게 역할을 위임합니다. 이 bean들은 Spring에 기본적으로 구현되어있지만 property 들을 커스터마이즈 하거나 상속받아서 대체하는게 가능합니다.이름 설명 HandlerMapping -request를 pre/post interceptor들에 따라 handler에게 맵핑합니다.
-@RequestMapping
을 지원하는RequestMappingHandlerMapping
과SimpleUrlHandlerMapping
두가지가 주요 구현체로 존재합니다.HandlerAdapter - Handler가 실제로 어떻게 실행되는지와 별개로 DispatcherServlet
이 request를 handler에 맵핑할 수 있도록 도와주는 역할을 합니다.
-@RequestMapping
같은 어노테이션이 달린 컨트롤러가 request를 처리하려면 어노테이션에 대한 처리를 해야하는데 이것을HandlerAdapter
에서 수행해 줍니다.HandlerExceptionResolver 에러 페이지 띄우기, 다른쪽으로 예외 던지기 등 Exception을 처리하는 전략을 담당합니다. ViewResolver Handler에서 리턴된 String
based view 이름을 response에 렌더링할 실제View
로 만들어주는 작업을 수행합니다.LocaleResolver
LocaleContextResolver사용자의 timezone에 맞는 Locale
을 가지고오는데 사용됩니다.MultipartResolver Multi-part request를 파싱하기 위한 라이브러리에서 사용가능한 추상화를 제공합니다. FlashMapManager Redirect와 같이 request의 attribute를 다른 request로 전달하기 위한 FlashMap
을 저장하고 꺼내오는데 사용됩니다.
Processing
DispatcherServlet
은 아래의 과정으로 request를 처리합니다.- Request의 attribute를 사용하여 해당 request를 처리할 수 있는 element에
WebApplicationContext
를 바인딩합니다.- Default로
DispatcherServlet.WEB_APPLICATION_CONTEXT_ATTRIBUTE
키에 따라 바인딩 됩니다.
- Default로
- Locale resolver가 필요한 경우라면 request에 resolver가 바인딩
- Theme를 사용하는 경우 theme resolver가 바인딩
- Multipart request면서 multipart resolver를 명시해둔 경우
MultipartHttpServletRequest
로 랩핑됩니다. - Request에 적합한 handler 검색 후 관련된 execution chain(preprocessor, postprocessor, controller)이 수행,
Annotated controller의 경우 view를 반환하는 대신HandlerAdapter
에서 response를 렌더 - Model이 반환된 경우 view가 렌더링 되며, 그렇지 않은경우 request는 이미 처리 된 것이기 때문에 view가 렌더링 되지 않음
- Request의 attribute를 사용하여 해당 request를 처리할 수 있는 element에
WebApplicationContext
에 정의된HandlerExceptionResolver
이 request 처리 과정에서 발생한 exception을 처리하는데 사용됩니다.DispatcherServlet
은 Servlet API에 명시된last-modification-date
값도 지원합니다.
Interception
- 모든
HanlderMapping
의 구현체는 handler interceptors를 지원 합니다. PreHandle
boolean
값을 리턴하며 handler가 수행되기 전에 실행됩니다.true
가 리턴되면 execution chain이 계속 수행되며,false
가 리턴되면 interceptor에서 요청 처리가 완료되었다고 가정하여 execution chain이 종료됩니다.
PostHandle
- Handler가 수행된 이후 실행됩니다.
HandlerAdapter
에서 요청이 처리되는 경우에는(@ResponseBody
,ResponseEntity
등) response에 추가적인 조작을 하기엔 너무 늦은 시점이 되기 때문에 그리 유용하지 못하며,
이 경우에는ResponseBodyAdvice
의 구현체를 추가하거나RequestMappingHandlerAdapter
bean을 추가해야 합니다.
afterCompletion
- Request가 완전히 종료된 이후에 수행됩니다.
View Resolution
- Spring MVC는 특별한 view 관련 기술을 사용하지 않고도 model을 렌더링 할 수 있도록
ViewResolver
,View
interface를 제공합니다. ViewResolver
는 view의 이름과 실제View
를 맵핑해 줍니다.
Handling
ViewResolver
bean 추가 하여 View resolver chain에 여러개의 view resolver를 등록 할 수 있습니다.
Redirecting
redirect:
prefix를 갖는 view 이름은 특별하게 취급되며 redirect에 사용됩니다.UrlBasedViewResolver
에서 위의 prefix를 인식하고 redirect가 필요한지 판단하게 됩니다.
- Controller에서
RedirectView
를 리턴한것과 동일한 효과를 갖지만 현재 context path를 기반으로 한 상대경로로 redirect 대상을 명시할 수 있습니다. - Controller에서
@ResponseStatus
를 명시한 경우RedirectView
에서 설정한 상태코드보다 우선 반영 됩니다.
Forwarding
forward:
prefix를 갖는 view 이름은RequestDispatcher.forward()
를 호출하는InternalResourceView
를 생성하며UrlBasedViewResolver
를 통해 처리됩니다.
Content Negotiation
ContentNegotiatingViewResolver
는 직접 view를 resolve 하지 않으며, view를 처리할 다른 resolver에게 위임하는데 사용됩니다.- HTTP 헤더나 query parameter로 위임 대상을 확인합니다.
Locale
LocaleResolver
를 사용하여 request 에 맞는 언어로 응답을 해 줄 수 있습니다.
'Docs > Spring' 카테고리의 다른 글
Spring Doc - Core - Transaction (0) 2021.05.03 Spring Doc - Core -IOC Container (0) 2021.05.03 Spring Doc - Core - AOP (0) 2021.05.03 - 현재 담당하는 서비스가 Spring5를 사용하진 않지만 5의 문서를 읽으면서 추가된 내용이 아니라 Spring framework 자체의 내용에 집중해볼 예정입니다.