首先从入口开始:org.springframework.web.servlet.DispatcherServlet
public class DispatcherServlet extends FrameworkServlet {
private static final String DEFAULT_STRATEGIES_PATH = "DispatcherServlet.properties";
/** Throw a NoHandlerFoundException if no Handler was found to process this request? *.*/
private boolean throwExceptionIfNoHandlerFound = false;
/** Perform cleanup of request attributes after include request?. */
private boolean cleanupAfterInclude = true;
/** MultipartResolver used by this servlet. */
@Nullable
private MultipartResolver multipartResolver;
/** LocaleResolver used by this servlet. */
@Nullable
private LocaleResolver localeResolver;
/** ThemeResolver used by this servlet. */
@Nullable
private ThemeResolver themeResolver;
/** List of HandlerMappings used by this servlet. */
@Nullable
private List<HandlerMapping> handlerMappings;
/** List of HandlerAdapters used by this servlet. */
@Nullable
private List<HandlerAdapter> handlerAdapters;
/** List of HandlerExceptionResolvers used by this servlet. */
@Nullable
private List<HandlerExceptionResolver> handlerExceptionResolvers;
/** RequestToViewNameTranslator used by this servlet. */
@Nullable
private RequestToViewNameTranslator viewNameTranslator;
/** FlashMapManager used by this servlet. */
@Nullable
private FlashMapManager flashMapManager;
/** List of ViewResolvers used by this servlet. */
@Nullable
private List<ViewResolver> viewResolvers;
public DispatcherServlet() {
super();
setDispatchOptionsRequest(true);
}
@Override
protected void onRefresh(ApplicationContext context) {
initStrategies(context);
}
/**
* Initialize the strategy objects that this servlet uses.
* <p>May be overridden in subclasses in order to initialize further strategy objects.
*/
protected void initStrategies(ApplicationContext context) {
/*
*从ApplicationContext中得到MultipartResolver.class类型
*且名为multipartResolver的Bean,如:
*1,CommonsMultipartResolver
*2,StandardServletMultipartResolver
*/
initMultipartResolver(context);
/*
*从ApplicationContext中得到LocaleResolver.class类型
*且名为localeResolver的Bean; 如果没有得到,则使用
*DispatcherServlet.properties文件中默认配置的对象
*/
initLocaleResolver(context);
/*
*从ApplicationContext中得到ThemeResolver.class类型
*且名为themeResolver的Bean; 如果没有得到,则使用
*DispatcherServlet.properties文件中默认配置的对象
*/
initThemeResolver(context);
/*
*如果detectAllHandlerMappings属性设置为ture(检测所有handlerMapping),
*则从ApplicationContext中得到所有HandlerMapping.class类的Bean;
*否则使用得到名为handlerMapping类型为HandlerMapping.class的Bean;
*---------------------
*例如以下常见的:
*1,RequestMappingHandlerMapping
*2,SimpleUrlHandlerMapping
*3,ControllerEndpointHandlerMapping
*4,WebMvcEndpointHandlerMapping
*5,BeanNameUrlHandlerMapping
*6,RouterFunctionMapping
*7,PropertySourcedRequestMappingHandlerMapping
*8,WelcomePageHandlerMapping
*9,CompositeHandlerMapping
*/
initHandlerMappings(context);
/*
*如果detectAllHandlerAdapters属性设置为ture(检测所有handlerAdapter),
*则从ApplicationContext中得到所有HandlerAdapter.class类的Bean;
*否则使用得到名为handlerAdapter类型为HandlerAdapter.class的Bean;
*---------------------
*例如以下常见的:
*1,SimpleServletHandlerAdapter
*2,SimpleControllerHandlerAdapter
*3,HttpRequestHandlerAdapter
*4,HandlerFunctionAdapter
*5,RequestMappingHandlerAdapter
*6,CompositeHandlerAdapter
*/
initHandlerAdapters(context);
/*
*如果detectAllHandlerExceptionResolvers属性设置为ture(检测所有HandlerExceptionResolver),
*则从ApplicationContext中得到所有HandlerExceptionResolver.class类的Bean;
*否则使用得到名为handlerExceptionResolver类型为HandlerExceptionResolver.class的Bean;
*---------------------
*例如以下常见的:
*1,SimpleMappingExceptionResolver
*2,ResponseStatusExceptionResolver
*3,DefaultHandlerExceptionResolver
*4,ExceptionHandlerExceptionResolver
*5,DefaultErrorAttributes
*6,HandlerExceptionResolverComposite
*7,CompositeHandlerExceptionResolver
*/
initHandlerExceptionResolvers(context);
/*
*从ApplicationContext中得到RequestToViewNameTranslator.class类型
*且名为viewNameTranslator的Bean; 如果没有得到,则使用
*DispatcherServlet.properties文件中默认配置的对象
*/
initRequestToViewNameTranslator(context);
/*
*如果detectAllViewResolvers属性设置为ture(检测所有lViewResolver),
*则从ApplicationContext中得到所有ViewResolver.class类的Bean;
*否则使用得到名为viewResolver类型为ViewResolver.class的Bean;
*---------------------
*例如以下常见的:
*1,InternalResourceViewResolver
*2,ResourceBundleViewResolver
*3,MustacheViewResolver
*4,XsltViewResolver
*5,TilesViewResolver
*6,XmlViewResolver
*7,BeanNameViewResolver
*8,ContentNegotiatingViewResolver
*9,GroovyMarkupViewResolver
*10,FreeMarkerViewResolver
*11,ViewResolverComposite
*/
initViewResolvers(context);
/*
*从ApplicationContext中得到FlashMapManager.class类型
*且名为flashMapManager的Bean; 如果没有得到,则使用
*DispatcherServlet.properties文件中默认配置的对象
*/
initFlashMapManager(context);
}
/**
* Exposes the DispatcherServlet-specific request attributes and delegates to {@link #doDispatch}
* for the actual dispatching.
*/
@Override
protected void doService(HttpServletRequest request, HttpServletResponse response) throws Exception {
logRequest(request);
// Keep a snapshot of the request attributes in case of an include,
// to be able to restore the original attributes after the include.
Map<String, Object> attributesSnapshot = null;
if (WebUtils.isIncludeRequest(request)) {
attributesSnapshot = new HashMap<>();
Enumeration<?> attrNames = request.getAttributeNames();
while (attrNames.hasMoreElements()) {
String attrName = (String) attrNames.nextElement();
if (this.cleanupAfterInclude || attrName.startsWith(DEFAULT_STRATEGIES_PREFIX)) {
attributesSnapshot.put(attrName, request.getAttribute(attrName));
}
}
}
// Make framework objects available to handlers and view objects.
request.setAttribute(WEB_APPLICATION_CONTEXT_ATTRIBUTE, getWebApplicationContext());
request.setAttribute(LOCALE_RESOLVER_ATTRIBUTE, this.localeResolver);
request.setAttribute(THEME_RESOLVER_ATTRIBUTE, this.themeResolver);
request.setAttribute(THEME_SOURCE_ATTRIBUTE, getThemeSource());
if (this.flashMapManager != null) {
FlashMap inputFlashMap = this.flashMapManager.retrieveAndUpdate(request, response);
if (inputFlashMap != null) {
request.setAttribute(INPUT_FLASH_MAP_ATTRIBUTE, Collections.unmodifiableMap(inputFlashMap));
}
request.setAttribute(OUTPUT_FLASH_MAP_ATTRIBUTE, new FlashMap());
request.setAttribute(FLASH_MAP_MANAGER_ATTRIBUTE, this.flashMapManager);
}
try {
doDispatch(request, response);
}
finally {
if (!WebAsyncUtils.getAsyncManager(request).isConcurrentHandlingStarted()) {
// Restore the original attribute snapshot, in case of an include.
if (attributesSnapshot != null) {
restoreAttributesAfterInclude(request, attributesSnapshot);
}
}
}
}
/**
* Process the actual dispatching to the handler.
* <p>The handler will be obtained by applying the servlet's HandlerMappings in order.
* The HandlerAdapter will be obtained by querying the servlet's installed HandlerAdapters
* to find the first that supports the handler class.
* <p>All HTTP methods are handled by this method. It's up to HandlerAdapters or handlers
* themselves to decide which methods are acceptable.
* @param request current HTTP request
* @param response current HTTP response
* @throws Exception in case of any kind of processing failure
*/
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);
}
}
}
}
}
小结:对请求处理的大体过程
-
检查是不是文件上传(Multipart),如果是则对Request进行解析返回包装后的HttpServletRequest
-
根据HttpServletRequest得到匹配的HandlerMapping,并返回HandlerMapping的getHandler方法返回的结果HandlerExecutionChain
如果返回的HandlerExecutionChain为null,当throwExceptionIfNoHandlerFound属性为ture(默认为false)时则抛出NoHandlerFoundException异常,否则直接响应404
-
使用HandlerExecutionChain的getHandler()方法的返回结果作为参数来查找匹配的HandlerAdapter
HandlerExecutionChain的getHandler()方法的返回结果(Handler)作为参数调用每个HandlerAdapter的supports方法,如果找到则返回该HandlerAdapter,否则抛出ServletException异常
-
使用Request,Response以及Handler作为参数执行HandlerAdapter的handle方法,并得到返回值ModelAndView
-
给ModelAndView设值默认的viewName值(如果返回的ModelAndView没有设置viewName)
如果viewNameTranslator不为null,则以HttpServletRequest作为参数执行其getViewName方法得到默认的名称(也可能为null)
-
捕获上面过程中执行得到的Exception(没发生异常则为null),并结合HttpServletRequest、HttpServletResponse、HandlerExecutionChain、ModelAndView作为参数执行processDispatchResult方法
1)如果Exception不为空,且不是ModelAndViewDefiningException异常,则执行processHandlerException方法返回ModelAndView;迭代执行每个HandlerExceptionResolver的resolveException方法,如果中途返回的ModelAndView不为空则返回,如果最终得到的ModelAndView为null
2)如果ModelAndView中的viewName不为空则遍历所有ViewResolver并执行resolveViewName方法的到View实例,如果最终得到的为null,则抛出ServletException异常; 如果viewName为空,则直接从ModelAndView对象中返回View实例,如果为空依然抛出异常。
3)执行View的render访问完成视图的渲染
-
清除Multipart
网友评论