욱'S 노트

Spring MVC - DispatcherServlet 본문

Programming/Spring MVC

Spring MVC - DispatcherServlet

devsun 2015. 6. 16. 16:47

스프링 MVC 프레임워크는 다른 웹 MVC 프레임워크 처럼 request-driven 이다. 중앙 서블릿이 요청을 컨트롤러로 디스패치하고 웹 어플리케이션 개발의 여러 기능들을 제공한다. 하지만 스프링 DispatcherServlet은 그것보다 더 많은 것을 한다. Spring IoC 컨테이너와 완벽하게 결합하고 Spring이 가지는 모든 다른 기능을 사용할 수 있다.

Dispacther 서블릿이 요청을 처리하는 워크플로우는 다음 다이어그램에 묘사되어 있다. pattern-savvy reader는 디스패쳐서블릿을 Front Controller 표현으로 인식한다.

디스패처 서블릿은 실제 서블릿이다. 일반적으로 우리에 web 어플리케이션에 정의되는 일반적인 서블릿과 동일하다. web.xml 에 URL 매핑을 이용하여 처리할 URL을 정의하고 디스패처 서블릿을 정의한다. 이것은 Java EE 표준 서블릿 설정이다. 다음 예제가 디스패처 서블릿과 mapping을 정의한 것이다.


<web-app>

    <servlet>

<servlet-name>example</servlet-name> 

<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> 

<load-on-startup>1</load-on-startup>

</servlet>

<servlet-mapping> 

<servlet-name>example</servlet-name> 

<url-pattern>/example/*</url-pattern>

    </servlet-mapping>

</web-app>


앞의 예제에서 /example로  시작하는 모든 요청은 DispatcherServlet에서 처리된다. Servlet 3.0이상에서는 프로그램으로 옵션을 정의할 수 있다. 아래는 위와 동일한 기능을 하는 web.xml 이다.


public class MyWebApplicationInitializer implements WebApplicationInitializer {

@Override

public void onStartup(ServletContext container) {

ServletRegistration.Dynamic registration = container.addServlet("dispatcher", new DispatcherServlet()); 

registration.setLoadOnStartup(1); 

registration.addMapping("/example/*");

}


WebApplicationInitializer 인터페이스는 Spring MVC에 의해 제공된 코드 기반 설정을 자동적으로 찾아서 Servlet 3 컨테이너를 초기화하기 위해 사용된다. 



위의 디스패처 서블릿 초기화를 보면 Spring MVC는 WEB-INF 디렉토리에  [servlet-name]-servlet.xml이라는 파일명을 찾고 거기에 있는 빈 정의를 생성한다. global scope에 동일한 이름이 있으면 오버라이드 한다. 

다음 디스패처 서블릿 설정을 살펴보자.


<web-app>

    <servlet>

<servlet-name>golfing</servlet-name> 

<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> 

<load-on-startup>1</load-on-startup>

    </servlet>

    <servlet-mapping>

        <servlet-name>golfing</servlet-name>

<url-pattern>/golfing/*</url-pattern> 

</servlet-mapping>

</web-app>


위의 서블리 설정을 보면 /WEB-INF/golfing- servlet.xml 파일일을 호출할 것이다. 파일은 스프링 MVC 컴포넌트들을 포함하고 있을 것이다. 해당 내용은 위치를 지정함으로써 변경할 수 있다. 


<web-app>

    <context-param>

<param-name>contextConfigLocation</param-name>

<param-value>/WEB-INF/root-context.xml</param-value> </context-param>

<servlet>

<servlet-name>dispatcher</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>dispatcher</servlet-name> 

<url-pattern>/*</url-pattern>

    </servlet-mapping>

    <listener>

<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class> 

</listener>

</web-app>


웹어플리케이션 컨텍스트는 ApplicationContext의 확장이다. 일반 어플리케이션 컨텍스트에 웹 어플리케이션에 필요한 추가적인 기능들을 추가한 것이다. 웹어플리케이션 컨텍스트는 서블릿 컨텍스트에 바운드되며 RequestContextUtils 클래스를 이용하여 만약 필요한다면 웹어플리케이션 컨텍스트에 접근할 수 있다.


Special Bean Types In the WebApplicationContext


스프링 디스패처 서블릿은 요청을 처리하고 적당한 뷰를 렌더링하기 위해 특별한 빈들을 사용한다. 이러한 빈들이 Spring MVC를 구성한다. 이러한 빈들은 Spring MVC에 의해 디폴트 빈들이 유지되고 초기화되므로 설정을 할 필요가 없다.


HandlerMapping - 들어오는 요청을 HandlerMapping 구현체가 다양하게 만든 기준에 기반한 전처리자(pre-processors)와 후처리자(post-processors)(핸들러 인터셉터)의 목록에 매핑한다. 대부분의 인기있는 구현체는 어노테이션이 붙은 컨트롤러를 지원하지만 그렇지 않은 구현체들도 존재한다.

HandlerAdapter - 핸들러가 실제로 호출되었는지 여부에 상관없이 DispatcherServlet이 요청에 매핑된 핸들러를 호출하도록 돕는다. 예를 들어 어노테이션이 붙은 컨트롤러를 호출하려면 다양한 어노테이션을 처리해야 한다. 그러므로 HandlerAdapter의 주요 목적은 이러한 세부내용에서 DispatcherServlet을 보호하는 것이다.

HandlerExceptionResolver - 예외를 뷰에 매핑하고 더 복잡한 예외 처리 코드도 사용할 수 있다.

ViewResolver - 논리적인 스프링 기반의 뷰 이름을 실제 View 타입으로 처리한다.

LocaleResolver - 국제화된 뷰화면을 제공할 수 있도록 클라이언트가 사용하는 로케일을 처리한다.

ThemeResolver - 개인화된 레이아웃을 제공하는 것처럼 웹 어플리케이션이 사용할 수 있는 테마를 처리한다.

MultipartResolver - HTML 폼에서 업로드하는 파일을 처리하는 등의 멀티파트(multi-part) 요청을 파싱한다.


Default DispatcherServlet Configuration


앞에서 언급했듯이 디스패처 서블릿은 특별한 빈들의 리스트를 유지한다. 이러한 빈들은 기본으로 사용할 수 있도록 제공한다. 이러한 정보는 DispatcherServlet이라는 파일에서 찾을 수 있다.


모든 특별한 빈들은 합당한 기본값을 가진다. 하지만 이러한 빈들이 제공한 값들이 변경될 수 있을 것이다. 예를 들어 InternalResourceViewResolver는 뷰파일의 부모 위치 prefix는 일반적으로 세팅 될 것이다.


세부적인 내용을 고려하지 않고 웹어플리케이션 컨텐스트는 특별한 빈을 설정할 수 있다는 것은 중요한 컨셉니다. 디폴트 구현체를 효울적으로 오버라이드할 수 있을 것이다. 만약 InternalViewResolver 설정한다면 기본 ViewResolver 구현체는 무시될 것이다.


DispatcherServlet Processing Sequence


디스패처 서블릿이 셋업한 후 요청은 지정된 디스패처 서블릿으로 들어오게 된다. 요청을 처리하는 순서는 다음과 같다.


• 웹어플리케이션 컨텍스트가 찾아진다. 처리중 컨트롤러나 다른 엘레멘트들이 사용할 수 있게 요청을 어트리뷰트로 바인딩한다. 기본적으로 키를 DispatcherServlet.WEB_APPLICATION_CONTEXT_ATTRIBUTE 를 이용한다.

  • 로케일 리졸버다 요청에 바인딩 된다. 프로세스 중 로케일에 대한 처리를 할 수 있기 위함이다. 만약 로케일 처리가 필요 없다면 필요없다.

  • 테마 리졸버가 요청에 바인딩 된다. 뷰와같으 어느 테마를 사용할지 결정할 수 있기 위함이다. 만약 테마 처리가 필요없다면 무시해도 된다.

  • 멀티파트 리졸버를 지정했다면 요청이 멀티파트인지 검사한다. 요청이 멀티파트라면 향후 처리를 위해 MultipartHttpServletRequest로 래핑된다.

  • 적절한 핸들러를 찾는다. 핸들러를 찾으면 모델을 준비하거나 렌더링하기 위해서 핸들러와 연결된 실행 체인을 실행한다.

  • 모델이 반환되면 뷰를 렌더링한다. 모델이 반환되지 않는면 뷰도 렌더링 되지 않는다. 요청이 이미 다 처리되었기 때문이다.

핸들러 익셉션 리졸버는 웹 어플리케이션내에 정의된다. 요청 처리중 발생한 익셉션을 캐치하기 위함이다. 익셉션 핸들러 리졸버를 정의함으로써 커스텀한 익셉션 처리를 수행할 수 있다.


디스패처 서블릿은 최종 변경 일자를 리턴할 수 있도록 지원한다. 이는 서블릿 API에 명시되어 있다. 특정한 요청의 최종 변경 일자를 판단하는 프로세스는 일방적이다. 디스패처 서블릿은 적당한 핸들러 매핑을 찾아내고 핸들러가 LastModified 인터페이스를 구현했는지 확인한다. 만약 그렇다면 getLastModified 메소드를 호출하여 결과를 클라이언트에 리턴한다.


디스패처 서블릿은 서블릿 초기화 파라미터를 추가함으로써 커스터마이징할 수 있다. 다음은 지원하는 파라미터 리스트이다.


contextClass- WebApplicationContext를 구현한 클래스로 해당 서블릿이 사용하는 컨텍스트를 인스턴스화한다. 기본적으로 XmlWebApplicationContext를 사용한다.

contextConfigLocation -  어디서 컨텍스트를 찾을 수 있는지를 나타내려고 컨텍스트 인스턴스에 (contextClass가 지정한) 전달하는 문자열이다. 문자열은 여러 컨텍스트를 지원하려고 여러 문자열(콤마로 구분한다)로 이루어질 수 있다. 여러 컨텍스트를 사용하는 경우에 빈의 위치는 두번 정의되는데 마지막 위치를 사용한다.

namespace - WebApplicationContext의 네임스페이스. 기본값은 [servlet-name]-servlet이다.


'Programming > Spring MVC' 카테고리의 다른 글

Spring MVC - Controllers  (0) 2015.06.17
Spring MVC - Introduction to Spring Web MVC framework  (0) 2015.06.16
Comments