[Spring Basic] DispatcherServlet
스프링 MVC의 디스패처 서블릿은 여러 개의 서블릿들에 대해 공통 부분을 따로 빼서 처리하는 역할을 수행한다. (프론트 컨트롤러)
클라이언트로부터 요청이 오면 우선 디스패처 서블릿이 요청을 받아 해당하는 컨트롤러의 메서드를 호출한 후 컨트롤러가 반환하는 뷰 이름을 받아오는 방식으로 진행된다.
이 과정에서 URL을 키, 메서드를 값으로 가지는 HandlerMapping과 HandlerAdapter가 사용된다.
HandlerMapping은 디스패처 서블릿이 클라이언트로부터 받은 요청을 어떤 컨트롤러가 처리할 지 결정한다.
HandlerAdapter는 HandlerMapping이 찾은 컨트롤러를 실행하고 그 결과를 적당한 객체로 변환한다.
요청이 왔을 때 디스패처 서블릿은 HandlerMapping에게 먼저 물어본 후 메서드를 호출하고, 해당하는 메서드는 어떤 HandlerAdapter가 호출할 수 있는지 확인한다.
ViewResolver는 실제 뷰 이름을 가져올 때 사용한다.
ViewResolver를 통해 실제 뷰 이름을 가져오고, 디스패처 서블릿은 뷰 이름을 바탕으로 registerForm에게 모델을 전달한다
public class DispatcherServlet extends FrameworkServlet {
public static final String MULTIPART_RESOLVER_BEAN_NAME = "multipartResolver";
public static final String LOCALE_RESOLVER_BEAN_NAME = "localeResolver";
public static final String THEME_RESOLVER_BEAN_NAME = "themeResolver";
...
private void initHandlerMappings(ApplicationContext context) {
this.handlerMappings = null;
if (this.detectAllHandlerMappings) {
// Find all HandlerMappings in the ApplicationContext, including ancestor contexts.
Map<String, HandlerMapping> matchingBeans =
BeanFactoryUtils.beansOfTypeIncludingAncestors(context, HandlerMapping.class, true, false);
if (!matchingBeans.isEmpty()) {
this.handlerMappings = new ArrayList<>(matchingBeans.values());
// We keep HandlerMappings in sorted order.
AnnotationAwareOrderComparator.sort(this.handlerMappings);
}
}
else {
try {
HandlerMapping hm = context.getBean(HANDLER_MAPPING_BEAN_NAME, HandlerMapping.class);
this.handlerMappings = Collections.singletonList(hm);
}
catch (NoSuchBeanDefinitionException ex) {
// Ignore, we'll add a default HandlerMapping later.
}
}
// Ensure we have at least one HandlerMapping, by registering
// a default HandlerMapping if no other mappings are found.
if (this.handlerMappings == null) {
this.handlerMappings = getDefaultStrategies(context, HandlerMapping.class);
if (logger.isTraceEnabled()) {
logger.trace("No HandlerMappings declared for servlet '" + getServletName() +
"': using default strategies from DispatcherServlet.properties");
}
}
for (HandlerMapping mapping : this.handlerMappings) {
if (mapping.usesPathPatterns()) {
this.parseRequestPath = true;
break;
}
}
}
/**
* Initialize the HandlerAdapters used by this class.
* <p>If no HandlerAdapter beans are defined in the BeanFactory for this namespace,
* we default to SimpleControllerHandlerAdapter.
*/
private void initHandlerAdapters(ApplicationContext context) {
this.handlerAdapters = null;
if (this.detectAllHandlerAdapters) {
// Find all HandlerAdapters in the ApplicationContext, including ancestor contexts.
Map<String, HandlerAdapter> matchingBeans =
BeanFactoryUtils.beansOfTypeIncludingAncestors(context, HandlerAdapter.class, true, false);
if (!matchingBeans.isEmpty()) {
this.handlerAdapters = new ArrayList<>(matchingBeans.values());
// We keep HandlerAdapters in sorted order.
AnnotationAwareOrderComparator.sort(this.handlerAdapters);
}
}
else {
try {
HandlerAdapter ha = context.getBean(HANDLER_ADAPTER_BEAN_NAME, HandlerAdapter.class);
this.handlerAdapters = Collections.singletonList(ha);
}
catch (NoSuchBeanDefinitionException ex) {
// Ignore, we'll add a default HandlerAdapter later.
}
}
// Ensure we have at least some HandlerAdapters, by registering
// default HandlerAdapters if no other adapters are found.
if (this.handlerAdapters == null) {
this.handlerAdapters = getDefaultStrategies(context, HandlerAdapter.class);
if (logger.isTraceEnabled()) {
logger.trace("No HandlerAdapters declared for servlet '" + getServletName() +
"': using default strategies from DispatcherServlet.properties");
}
}
}
}
위의 소스코드는 실제 DispatcherServlet.java의 일부이다.
HandlerMapping과 HandlerAdapter를 사용해 컨트롤러를 찾고 실행함을 확인할 수 있다.
스프링 MVC 에서는 일반적으로 서블릿으로 디스패처 서블릿 하나만 사용해 리소스를 효과적으로 관리한다.
반응형
'Spring > Spring' 카테고리의 다른 글
[Spring Basic] JUnit Test Framework (0) | 2022.07.09 |
---|---|
[Spring Basic] 파라미터의 변환과 검증 (0) | 2022.06.24 |
[Spring Basic] 리다이렉트와 포워드 (0) | 2022.05.12 |
[Spring Basic] 서블릿과 JSP (0) | 2022.05.05 |
[Spring Basic] 서블릿과 출력 (0) | 2022.04.13 |
댓글
이 글 공유하기
다른 글
-
[Spring Basic] JUnit Test Framework
[Spring Basic] JUnit Test Framework
2022.07.09 -
[Spring Basic] 파라미터의 변환과 검증
[Spring Basic] 파라미터의 변환과 검증
2022.06.24 -
[Spring Basic] 리다이렉트와 포워드
[Spring Basic] 리다이렉트와 포워드
2022.05.12 -
[Spring Basic] 서블릿과 JSP
[Spring Basic] 서블릿과 JSP
2022.05.05