浏览器发送一个请求给DispatcherServlet (在doDispatch(request, response)中);DispatcherServlet将请求交给HandleMapping 获取处理器执行链;DispatcherServlet获得执行链中的handle;遍历所有处理器适配器,获得支持handle的具体的适配器;处理器执行链执行前置处理(返回false就不再往下执行);然后由DispatcherServlet将请求、响应和handle交给处理器适配器处理,HandleAdapter执行控制器Controller中具体的方法返回ModelAndView;处理器执行链执行后置处理;通过试图解析器解析准确试图,将模型数组放到request域中渲染试图;将试图返回前端页面。

HandlerMapping接口就一个作用:根据request获取handle和拦截器数组。


概念理解:

handler在这里,是指包含了我们请求的Controller类和 url映射的Method方法的对象。

一个控制器Controller中有内部N个方法== N个Handler

M个控制器=M×N个Handler

M×N个Hanlder存放在handlerMappings中

 
 
public interface HandlerMapping {
 HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception;
}
HandlerExecutionChain包含一个handle和一个拦截器数组。
public class HandlerExecutionChain {
 private final Object handler;
 private HandlerInterceptor[] interceptors;
~
}
public class HttpRequestHandlerAdapter implements HandlerAdapter {
 @Override
 public boolean supports(Object handler) {
  return (handler instanceof HttpRequestHandler);
 }
 @Override
 public ModelAndView handle(HttpServletRequest request, HttpServletResponse response, Object handler)
   throws Exception {
  ((HttpRequestHandler) handler).handleRequest(request, response);
  return null;
 }


进入DispatcherServlet 执行onRefresh,然后执行初始化方法initStrategies。然后调用doService——>doDispatch。

根据继承关系执行Servlet的步骤:

init...............initStrategies

service...........doService

/**
* This implementation calls {@link #initStrategies}.
*/
@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) {
initMultipartResolver(context);
initLocaleResolver(context);
initThemeResolver(context);
initHandlerMappings(context);
initHandlerAdapters(context);
initHandlerExceptionResolvers(context);
initRequestToViewNameTranslator(context);
initViewResolvers(context);
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 {
if (logger.isDebugEnabled()) {
String resumed = WebAsyncUtils.getAsyncManager(request).hasConcurrentResult() ? " resumed" : "";
logger.debug("DispatcherServlet with name '" + getServletName() + "'" + resumed +
" processing " + request.getMethod() + " request for [" + getRequestUri(request) + "]");
} // Keep a snapshot of the request attributes in case of an include,
// to be able to restore the original attributes after the include.
     // 保存request中的所有属性
Map<String, Object> attributesSnapshot = null;
if (WebUtils.isIncludeRequest(request)) {
attributesSnapshot = new HashMap<String, Object>();
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()); 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);           // 遍历handlerMappings获取HandlerExecutionChain实例(handle和HandlerInterceptor[])
mappedHandler = getHandler(processedRequest);
if (mappedHandler == null || mappedHandler.getHandler() == null) {
noHandlerFound(processedRequest, response);
return;
} // Determine handler adapter for the current request.
          // 通过 处理器执行链 匹配 处理器适配器 实例
          // 获取 处理器执行链 HandlerExecutionChain中 handle,查找并返回支持handle的 处理器适配器HandlerAdapter
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 (logger.isDebugEnabled()) {
logger.debug("Last-Modified value for [" + getRequestUri(request) + "] is: " + lastModified);
}
if (new ServletWebRequest(request, response).checkNotModified(lastModified) && isGet) {
return;
}
}
          //执行所有自定义的拦截器的preHandle(前置处理)方法
if (!mappedHandler.applyPreHandle(processedRequest, response)) {
return;
} // Actually invoke the handler.
          // 执行handle返回ModelAndView实例
          // 使用匹配的 HandlerAdapter 处理请求
          // 此处将调用用户自定义的Controller类中的方法
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);
}
}
}
}

AbstractHandlerMapping的  getHandler方法,通过HandlerMapping获取处理器执行链:

public final HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception {
Object handler = getHandlerInternal(request);//获取hangdle
if (handler == null) {
handler = getDefaultHandler();
}
if (handler == null) {
return null;
}
// Bean name or resolved handler?
if (handler instanceof String) {
String handlerName = (String) handler;
handler = getApplicationContext().getBean(handlerName);
}
     //添加拦截器
HandlerExecutionChain executionChain = getHandlerExecutionChain(handler, request);
if (CorsUtils.isCorsRequest(request)) {
CorsConfiguration globalConfig = this.globalCorsConfigSource.getCorsConfiguration(request);
CorsConfiguration handlerConfig = getCorsConfiguration(handler, request);
CorsConfiguration config = (globalConfig != null ? globalConfig.combine(handlerConfig) : handlerConfig);
executionChain = getCorsHandlerExecutionChain(request, executionChain, config);
}
return executionChain;
}
 protected HandlerExecutionChain getHandlerExecutionChain(Object handler, HttpServletRequest request) {
  HandlerExecutionChain chain = (handler instanceof HandlerExecutionChain ?
    (HandlerExecutionChain) handler : new HandlerExecutionChain(handler));

    //根据request的url匹配所有拦截器,将拦截器放到处理器执行链中 
  String lookupPath = this.urlPathHelper.getLookupPathForRequest(request);
  for (HandlerInterceptor interceptor : this.adaptedInterceptors) {
   if (interceptor instanceof MappedInterceptor) {
    MappedInterceptor mappedInterceptor = (MappedInterceptor) interceptor;
    if (mappedInterceptor.matches(lookupPath, this.pathMatcher)) {
     chain.addInterceptor(mappedInterceptor.getInterceptor());
    }
   }
   else {
    chain.addInterceptor(interceptor);
   }
  }
  return chain;
 }
 

springmvc执行流程 源码分析的更多相关文章

  1. springMvc的执行流程(源码分析)

    1.在springMvc中负责处理请求的类为DispatcherServlet,这个类与我们传统的Servlet是一样的.我们来看看它的继承图 2. 我们发现DispatcherServlet也继承了 ...

  2. Springboot中mybatis执行逻辑源码分析

    Springboot中mybatis执行逻辑源码分析 在上一篇springboot整合mybatis源码分析已经讲了我们的Mapper接口,userMapper是通过MapperProxy实现的一个动 ...

  3. springmvc拦截器入门及其执行顺序源码分析

    springmvc拦截器是偶尔会用到的一个功能,本案例来演示一个较简单的springmvc拦截器的使用,并通过源码来分析拦截器的执行顺序的控制.具体操作步骤为:1.maven项目引入spring依赖2 ...

  4. SpringMVC由浅入深day01_6源码分析(了解)

    6 源码分析(了解) 通过前端控制器源码分析springmvc的执行过程. 入口 第一步:前端控制器接收请求 调用doDiapatch 第二步:前端控制器调用处理器映射器查找 Handler 第三步: ...

  5. Django rest framework 的认证流程(源码分析)

    一.基本流程举例: urlpatterns = [ url(r'^admin/', admin.site.urls), url(r'^users/', views.HostView.as_view() ...

  6. (五)myBatis架构以及SQlSessionFactory,SqlSession,通过代理执行crud源码分析---待更

    MyBatis架构 首先MyBatis大致上可以分为四层: 1.接口层:这个比较容易理解,就是指MyBatis暴露给我们的各种方法,配置,可以理解为你import进来的各种类.,告诉用户你可以干什么 ...

  7. springMvc Velocity tool 源码分析

    在公司使用pandoraboot配置了velocity tool,一直不明白官方支持的init方法没有调用,而且不支持velocity tool 1.x版本的定义(1.x和2.x的定义见下面),而另一 ...

  8. Spring Securtiy 认证流程(源码分析)

    当用 Spring Security 框架进行认证时,你可能会遇到这样的问题: 你输入的用户名或密码不管是空还是错误,它的错误信息都是 Bad credentials. 那么如果你想根据不同的情况给出 ...

  9. Spring之SpringMVC的RequestToViewNameTranslator(源码)分析

    前言 SpringMVC如果在处理业务的过程中发生了异常,这个时候是没有一个完整的ModelAndView对象返回的,它应该是怎么样处理呢?或者说应该怎么去获取一个视图然后去展示呢.下面就是要讲的Re ...

随机推荐

  1. spring拾遗(一)——@Value注入static属性

    一般情况的下的@Value是用在非静态方法上的,如下: import org.springframework.beans.factory.annotation.Value; import org.sp ...

  2. PatBlt

    PatBlt     该函数使用当前选入指定设备环境中的刷子绘制给定的矩形区域.通过使用给出的光栅操作来对该刷子的像素和表面像素进行组合. 原型: BOOL PatBlt(     HDC hdc,  ...

  3. sqlserver job 执行时间

    select instance_id,jh.run_date,jh.job_id,jh.step_name, case jh.run_status then 'failed' then 'Succee ...

  4. 学习 java 编程语言两个月来的感受

    今天是我接触java编程的第81天, 现在的感受是觉得非常快乐, 每次看着自己的写的代码能成功运行的时候那种喜悦是无法言表的, 最初接触电脑还是在小学, 后来到了初中觉得电脑无非就是点点鼠标, 按按键 ...

  5. 简单API练手:(1)复制自身程序到windows目录和系统目录下;(2)获得系统的相关信息。

    1.复制自身程序到windows目录和系统目录下: #include <windows.h> #include <stdio.h> #include <string.h& ...

  6. 64. Minimum Path Sum (Graph; DP)

    Given a m x n grid filled with non-negative numbers, find a path from top left to bottom right which ...

  7. MacOS下打包Python应用

    在MacOS下开发的Python应用,不是Web Application,开发好以后,如何给用户使用呢?用户的操作系统也是MacOS 使用py2app打包        一.软件环境          ...

  8. socket的protocal参数

    Documentation for socket() on Linux is split between various manpages including ip(7) that specifies ...

  9. golang apns升级到http2

    记录一下golang中升级apns,使用http2替换http1.1的详细过程. apns使用http2的好处就不用再说了,网上一搜一堆信息.苹果的apns推送在2015年8月就支持了http2协议, ...

  10. 在Linux(Ubuntu)下安装Arial、Times New Roman等字体

    在Linux下做文档.作图的时候,可能需要用到Arial和Times New Roman等字体.但是由于版权问题,Linux一般是不直接提供这些字体的. 注意字体也是有版权的!不过有版权也不代表一定会 ...