1. 简介
HTTP请求处理程序/控制器的中央调度器,例如用于web UI控制器或基于HTTP的远程服务导出器。分派给已注册的处理程序以处理web请求,从而提供方便的映射和异常处理工具。
这个servlet非常灵活:它可以用于任何工作流,并安装适当的适配器类。它提供了以下功能,使其区别于其他请求驱动的web MVC框架:
-
它基于JavaBeans配置机制。
-
它可以使用任何基于HandlerMapping接口的实现(预构建或作为应用程序的一部分提供)来控制请求到handler对象的路由。默认值为org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping和org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping. HandlerMapping对象可以在servlet的应用程序上下文中定义为bean,实现HandlerMapping接口,覆盖默认HandlerMapping(如果存在)。HandlerMappings可以被赋予任何bean名称(它们是按类型测试的)。
-
它可以使用任何handleAdapter;这允许使用任何处理程序接口,默认适配器为org.springframework.web.servlet.mvc.HttpRequestHandlerAdapter, org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter,Spring的org.springframework.web.HttpRequestHandler和org.springframework.web.servlet.mvc.Controller 接口。违约org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter文件也将注册。handleAdapter对象可以作为bean添加到应用程序上下文中,从而覆盖默认的handleAdapter。与HandlerMappings一样,HandlerAdapter可以被赋予任何bean名称(它们是按类型测试的)。
-
调度器的异常解决策略可以通过HandlerExceptionResolver指定,例如将某些异常映射到错误页。默认值为org.springframework.web.servlet.mvc.method.annotation.ExceptionHandlerExceptionResolver, org.springframework.web.servlet.mvc.annotation.ResponseStatusExceptionResolver,以及org.springframework.web.servlet.mvc.support.DefaultHandlerExceptionResolver。这些handlerExceptionResolver可以通过应用程序上下文重写。HandlerExceptionResolver可以被赋予任何bean名称(它们是按类型测试的)。
-
它的视图解析策略可以通过ViewResolver实现指定,将符号视图名称解析为视图对象。默认值为org.springframework.web.servlet.view.InternalResourceViewResolver. ViewResolver对象可以作为bean添加到应用程序上下文中,从而覆盖默认的ViewResolver。ViewResolver可以被赋予任何bean名称(它们是按类型测试的)。
-
如果用户未提供视图或视图名称,则配置的RequestToViewNameTranslator将当前请求转换为视图名称。对应的bean名称是“viewNameTranslator”;默认值是org.springframework.web.servlet.view.DefaultRequestToViewNameTranslator.
-
调度器解决multipart 请求的策略由MultipartResolver 实现决定。包括Apache Commons FileUpload 和 Servlet 3的实现;典型的选择是org.springframework.web.multipart.commons.CommonsMultipartResolver. MultipartResolver 名称是“multipartResolver”;默认值是none。
-
它的locale解析策略由LocaleResolver决定。开箱即用的实现通过HTTP接受头、cookie或会话工作。LocaleResolver bean名称是“localeResolver”;默认值是org.springframework.web.servlet.i18n.AcceptHeaderLocaleResolver。
-
它的主题分解策略由主题求解器决定。包括固定主题、cookie和会话存储的实现。ThemeResolver bean名称是“themeResolver”;默认值是org.springframework.web.servlet.theme.FixedThemeResolver.
注意:@RequestMapping注释只有在调度器中存在相应的HandlerMapping(对于类型级注释)和/或HandlerAdapter(对于方法级注释)时才会被处理。这是默认情况。但是,如果要定义自定义HandlerMappings或HandlerAdapter,则需要确保也定义了相应的自定义RequestMappingHandlerMapping和/或RequestMappingHandlerAdapter,前提是要使用@RequestMapping。
web应用程序可以定义任意数量的Dispatchers服务。每个servlet都将在自己的命名空间中运行,并用映射、处理程序等加载自己的应用程序上下文通过org.springframework.web.context.ContextLoaderListener,如果有,将共享。
从Spring3.1开始,DispatcherServlet现在可以注入web应用程序上下文,而不是在内部创建自己的上下文。这在Servlet3.0+环境中非常有用,它支持对Servlet实例进行编程注册。有关详细信息,请参阅DispatcherServlet(WebApplicationContext)javadoc。
2. 类结构

处理实际分派给handler程序。
handler程序将通过按顺序应用servlet的HandlerMappings来获得。handleAdapter将通过查询servlet安装的handleAdapter来获得,以找到第一个支持处理程序类的handleAdapter。所有HTTP方法都由此方法处理。由handleAdapter或处理程序自己决定哪些方法是可接受的。
protected void doDispatch(HttpServletRequest request, HttpServletResponse response) throws Exception {
HttpServletRequest processedRequest = request;
HandlerExecutionChain mappedHandler = null;
boolean multipartRequestParsed = false;
WebAsyncManager asyncManager = WebAsyncUtils.getAsyncManager(request);
try {
ModelAndView mv = null;
Exception dispatchException = null;
try {
processedRequest = checkMultipart(request);
multipartRequestParsed = (processedRequest != request);
// Determine handler for the current request.
mappedHandler = getHandler(processedRequest);
if (mappedHandler == null) {
noHandlerFound(processedRequest, response);
return;
}
// Determine handler adapter for the current request.
HandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler());
// Process last-modified header, if supported by the handler.
String method = request.getMethod();
boolean isGet = "GET".equals(method);
if (isGet || "HEAD".equals(method)) {
long lastModified = ha.getLastModified(request, mappedHandler.getHandler());
if (new ServletWebRequest(request, response).checkNotModified(lastModified) && isGet) {
return;
}
}
if (!mappedHandler.applyPreHandle(processedRequest, response)) {
return;
}
// Actually invoke the handler.
mv = ha.handle(processedRequest, response, mappedHandler.getHandler());
if (asyncManager.isConcurrentHandlingStarted()) {
return;
}
applyDefaultViewName(processedRequest, mv);
mappedHandler.applyPostHandle(processedRequest, response, mv);
}
catch (Exception ex) {
dispatchException = ex;
}
catch (Throwable err) {
// As of 4.3, we're processing Errors thrown from handler methods as well,
// making them available for @ExceptionHandler methods and other scenarios.
dispatchException = new NestedServletException("Handler dispatch failed", err);
}
processDispatchResult(processedRequest, response, mappedHandler, mv, dispatchException);
}
catch (Exception ex) {
triggerAfterCompletion(processedRequest, response, mappedHandler, ex);
}
catch (Throwable err) {
triggerAfterCompletion(processedRequest, response, mappedHandler,
new NestedServletException("Handler processing failed", err));
}
finally {
if (asyncManager.isConcurrentHandlingStarted()) {
// Instead of postHandle and afterCompletion
if (mappedHandler != null) {
mappedHandler.applyAfterConcurrentHandlingStarted(processedRequest, response);
}
}
else {
// Clean up any resources used by a multipart request.
if (multipartRequestParsed) {
cleanupMultipart(processedRequest);
}
}
}
}
网友评论