ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • Spring Doc - Core - Web MVC
    Docs/Spring 2021. 5. 3. 20:14

    Spring framework Document 읽기

    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를 부트스트랩 하며 이때 선언된 FilterServlet 도 함께 감지(detect)하여 컨테이너에 등록됩니다.

    • DispatcherServlet 의 설정을 위해서 WebApplicationContext 가 사용됩니다. WebApplicationContextServletContext 와 연관된 Servlet 에 대한 링크를 가지고 있으며 ServletContext 에 바인딩 되어 있기 때문에 어플리케이션에서 WebApplicationContext 에 접근이 필요한 경우 RequestContextUtils 의 static 메서드를 통해 접근할 수 있습니다.

    Special Bean Types

    • DispatcherServlet 은 request를 처리하기 위해 특별한 bean들에게 역할을 위임합니다. 이 bean들은 Spring에 기본적으로 구현되어있지만 property 들을 커스터마이즈 하거나 상속받아서 대체하는게 가능합니다.
    • 이름 설명
      HandlerMapping -request를 pre/post interceptor들에 따라 handler에게 맵핑합니다.
      -@RequestMapping 을 지원하는 RequestMappingHandlerMappingSimpleUrlHandlerMapping 두가지가 주요 구현체로 존재합니다.
      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를 처리합니다.
      1. Request의 attribute를 사용하여 해당 request를 처리할 수 있는 element에 WebApplicationContext 를 바인딩합니다.
        • Default로 DispatcherServlet.WEB_APPLICATION_CONTEXT_ATTRIBUTE 키에 따라 바인딩 됩니다.
      2. Locale resolver가 필요한 경우라면 request에 resolver가 바인딩
      3. Theme를 사용하는 경우 theme resolver가 바인딩
      4. Multipart request면서 multipart resolver를 명시해둔 경우 MultipartHttpServletRequest 로 랩핑됩니다.
      5. Request에 적합한 handler 검색 후 관련된 execution chain(preprocessor, postprocessor, controller)이 수행,
        Annotated controller의 경우 view를 반환하는 대신 HandlerAdapter 에서 response를 렌더
      6. Model이 반환된 경우 view가 렌더링 되며, 그렇지 않은경우 request는 이미 처리 된 것이기 때문에 view가 렌더링 되지 않음
    • 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

    댓글

Designed by Tistory.