본문 바로가기
4. Backend Development/1. Spring Framework

6. DispatcherServlet

by H232C 2020. 9. 1.

DispatcherServlet 초기화
다음의 특별한 타입의 빈들을 찾거나, 기본 전략에 해당하는 빈들을 등록한다.
● HandlerMapping: 핸들러를 찾아주는 인터페이스
● HandlerAdapter: 핸들러를 실행하는 인터페이스
● HandlerExceptionResolver
● ViewResolver
● ...

DispatcherServlet 동작 순서
1. 요청을 분석한다. (로케일, 테마, 멀티파트 등)
2. (
핸들러 맵핑에게 위임하여) 요청을 처리할 핸들러를 찾는다.
3. (
등록되어 있는 핸들러 어댑터 중에) 해당 핸들러를 실행할 수 있는 핸들러 어댑터를 찾는다.
4.
찾아낸 핸들러 어댑터를 사용해서 핸들러의 응답을 처리한다.
 
핸들러의 리턴값을 보고 어떻게 처리할지 판단한다.
  ● 뷰 이름에 해당하는 뷰를 찾아서 모델 데이터를 랜더링한다.
  ● @ResponseEntity가 있다면 Converter를 사용해서 응답 본문을 만들고.
5. (
부가적으로) 예외가 발생했다면, 예외 처리 핸들러에 요청 처리를 위임한다. 6. 최종적으로 응답을 보낸다.


Servlet Context에 등록되어 있는 ApplicationContext : Root WebApplicationContext
DispatcherServlet은 Root WebApplicationContext를 상속받는 Servlet WebApplicationContext를 생성한다.

이런 상속 관계를 만드는 이유 : Root WebApplicationContext(Services, Repository)는 다른 서블릿도 공용으로 사용
DispatcherServlet에서 만든 WebApplicationContext(Controllers, ViewResolver, HandlerMapping..)는 해당 DispatcherServlet 내에서만 스콥이 설정됨 (다른 서블릿에서는 해당 서블릿을 모른다.) 그래서 Root WebApplicationContext의 경우 웹과 관련되어 있는게 없다. (디스패처 서블릿을 다중으로 사용하지 않을경우 상속 관계를 만들지 않고 디스페처 서블릿에서 빈을 모두 등록하여 사용)

- web.xml

<!DOCTYPE web-app PUBLIC
 "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
 "http://java.sun.com/dtd/web-app_2_3.dtd" >

<web-app>
  <display-name>Archetype Created Web Application</display-name>

  <context-param>
    <param-name>contextClass</param-name>
    <param-value>org.springframework.web.context.support.AnnotationConfigWebApplicationContext</param-value>
  </context-param>

  <context-param>
    <param-name>contextConfigLocation</param-name>
    <param-value>servlet.AppConfig</param-value>
  </context-param>

  <!--  Spring IoC 컨테이너를 리스너가 적용하는데 적용시 Spring IoC 컨테이너는 Context-param을 참조하여 생성된다. -->
  <!--  servlet.AppConfig 파일의 설정을 참조하여 생성 -->

<!--  <filter>-->
<!--    <filter-name>myFilter</filter-name>-->
<!--    <filter-class>servlet.MyFilter</filter-class>-->
<!--  </filter>-->

<!--  <filter-mapping>-->
<!--    <filter-name>myFilter</filter-name>-->
<!--    <servlet-name>hello</servlet-name>-->
<!--  </filter-mapping>-->

<!--  <listener>-->
<!--    <listener-class>servlet.MyListener</listener-class>-->
<!--  </listener>-->
  <listener>
    <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
  </listener>
<!--  Spring IoC 컨테이너를 서블릿 애플리케이션의 생명주기에 맞추어 바인딩 해주는 코드 -->
<!--  서블릿 초기화시 Spring IoC 컨테이너를 연동해주고 종료시 연동을 종료 시켜줌 -->


<!--    <servlet>-->
<!--      <servlet-name>hello</servlet-name>-->
<!--      <servlet-class>servlet.HelloServlet</servlet-class>-->
<!--    </servlet>-->

<!--    <servlet-mapping>-->
<!--      <servlet-name>hello</servlet-name>-->
<!--      <url-pattern>/hello</url-pattern>-->
<!--    </servlet-mapping>-->

  <servlet>
    <servlet-name>app</servlet-name>
    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
    <init-param>
      <param-name>contextClass</param-name>
      <param-value>org.springframework.web.context.support.AnnotationConfigWebApplicationContext</param-value>
    </init-param>
    <init-param>
      <param-name>contextConfigLocation</param-name>
      <param-value>servlet.WebConfig</param-value>
    </init-param>
<!--    자바 설정을 사용하려면 설정해야 함-->
  </servlet>
  
  <servlet-mapping>
    <servlet-name>app</servlet-name>
    <url-pattern>/app/*</url-pattern>
  </servlet-mapping>
</web-app>

- AppConfig.java

package servlet;

import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.stereotype.Controller;

@Configuration
@ComponentScan(excludeFilters = @ComponentScan.Filter(Controller.class)) // ContextLoaderListener는 Root WebApplicationContext를 생성할떄 Controller는 뺴고 만든다.
public class AppConfig {
}

- WebConfig.java

package servlet;

import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.stereotype.Controller;

@Configuration
@ComponentScan(useDefaultFilters = false, includeFilters = @ComponentScan.Filter(Controller.class)) // 컨트롤러만 빈으로 등록
public class WebConfig {
}

- HomeController.java

package servlet;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class HomeController {

    @Autowired
    HelloService helloService;

    @GetMapping
    public String hello(){
        return "Hello, " + helloService.getName();
    }
}

HandlerMapping
● RequestMappingHandlerMapping

HandlerAdapter
● RequestMappingHandlerAdapter

ViewResolver
● InternalResourceViewResolver

InternalResourceViewResolver
● Prefix
● Suffix

DispatcherSerlvet의 기본 전략
● DispatcherServlet.properties

MultipartResolver
파일 업로드 요청 처리에 필요한 인터페이스
● HttpServletRequestMultipartHttpServletRequest로 변환해주어 요청이 담고 있는 File을 꺼낼 수 있는 API 제공.

LocaleResolver
클라이언트의 위치(Locale) 정보를 파악하는 인터페이스
기본 전략은 요청의 accept-language를 보고 판단.

ThemeResolver
애플리케이션에 설정된 테마를 파악하고 변경할 수 있는 인터페이스
참고: https://memorynotfound.com/spring-mvc-theme-switcher-example/

'4. Backend Development > 1. Spring Framework' 카테고리의 다른 글

8. Spring WEB MVC  (0) 2020.09.28
7. Spring boot  (0) 2020.09.24
5. Servlet  (0) 2020.09.01
4. MacOS Security Management System  (0) 2020.07.21
3. Spring Framework 기반 웹 프로젝트  (0) 2020.06.09

댓글