Spring Mvc原理分析(一)
阅读原文时间:2021年08月31日阅读:1

Servlet生命周期了解

Servlet的生命(周期)是由容器(eg:Tomcat)管理的,换句话说,Servlet程序员不能用代码控制其生命。

加载和实例化:时机取决于web.xml的定义,如果有x则在容器启动时(eg:SSM),反之则在第一次针对这个Servlet的请求发生时(eg:Spring Boot)。

初始化(init):实例化后会立马进行初始化,也就是执行init方法,init方式只会执行一次。

请求处理:初始化后,Servlet就可以接受请求了,基本方式是执行Servlet接口中的service方法。

终止服务:容器会在合适的时候销毁某个Servlet对象,这个策略取决于容器的开发者/商,销毁时destroy方法会被调用。

核心处理请求流程图

入口

前端控制器DispatcherServlet也是一个Servlet,他父类的父类HttpServletBean覆写了Servlet接口的init方法,在容器第一次加载或者第一次请求时会触发(延迟加载),这个方法是Sring Mvc初始化的入口。

启动初始化

  1. Spring容器启动过程,会执行Bean的加载、创建和初始化,此处以Controller层为例分析,暂不关注其他类型资源。

  2. RequestMappingHandlerMapping类也是其中一个Bean,负责解析所有标识有@Controller或者@RequestMapping注解的Bean。

  3. RequestMappingHandlerMapping的父类实现了InitializingBean接口,覆写了afterPropertiesSet()方法,该接口是Spring的扩展点之一,在Bean初始化过程中,所i有属性注入完毕之后,会执行一系列回调(回调入口:AbstractAutowireCapableBeanFactory#initializeBean),其中一个回调会验证当前类是否实现了InitializingBean接口,如果实现了会调用afterPropertiesSet()方法,此方法是解析Controller层路径和方法对应关系的入口。

  4. 解析完毕之后会存储在AbstractHandlerMethodMapping#MappingRegistry中,控制器方法HandlerMethod存储了当前路径对应方法的主要信息,它只负责准备数据,封装数据,而而不提供具体使用的方式方法。

  5. 在接收请求时会先根据路径从urlLookup 中获取匹配条件,然后根据匹配条件获取控制器方法HandlerMethod。

    class MappingRegistry {
    // T:RequestMappingInfo => <请求匹配条件,控制器方法>
    private final Map mappingLookup = new LinkedHashMap<>();
    // T:RequestMappingInfo => <路径,请求匹配条件>
    private final MultiValueMap urlLookup = new LinkedMultiValueMap<>();
    }

    public class HandlerMethod {
    /** Logger that is available to subclasses */
    protected final Log logger = LogFactory.getLog(getClass());
    // Web控制器方法所在的Web控制器bean。可以是字符串,代表bean的名称;也可以是bean实例对象本身。
    private final Object bean;
    // Bean工程,如果bean属性是Sring的beanName就可以用beanName获取到对应的bean作用Handler
    @Nullable
    private final BeanFactory beanFactory;
    // Web控制器方法所在的Web控制器bean的类型,如果该bean被代理,这里记录的是被代理的用户类信息
    private final Class beanType;
    // Web控制器方法
    private final Method method;
    private final Method bridgedMethod;
    // Web控制器方法的参数信息:所在类所在方法,参数,索引,参数类型
    private final MethodParameter[] parameters;
    // 注解@ResponseStatus的code属性
    @Nullable
    private HttpStatus responseStatus;
    // 注解@ResponseStatus的reason属性
    @Nullable
    private String responseStatusReason;
    @Nullable
    private HandlerMethod resolvedFromHandlerMethod;
    ….
    }

protected void initStrategies(ApplicationContext context) {
    // 初始化文件解析器,用于支持服务器的文件上传
   initMultipartResolver(context);
   // 初始化国际化解析器,用来提供国际化功能;
   initLocaleResolver(context);
   // 初始化主题解析器,用来提供皮肤主题功能;
   initThemeResolver(context);
   // 初始化处理器映射器
   initHandlerMappings(context);
   // 初始化处理器适配器,为不同的处理器提供上下文运行环境;
   initHandlerAdapters(context);
   // 处理器异常解析器,用来解析处理器产生的异常;
   initHandlerExceptionResolvers(context);
   // 初始化视图逻辑名称转换器,根据逻辑视图的名称找到具体的视图。
   // 当处理器没有返回逻辑视图名时,将请求的URL自动映射为逻辑视图名;
   initRequestToViewNameTranslator(context);
   // 初始化视图解析器,当控制器返回后,通过试图解析器会把逻辑视图名进行解析,从而定位实际视图;
   initViewResolvers(context);
   // 初始化FlashMap管理器接口,负责重定向时,保存参数到临时存储中
   initFlashMapManager(context);
}

映射器初始化

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 {
          // 根据名称获取指定的bean:handlerMapping
         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) {
       // 获取默认的处理器映射
       // 从【DispatcherServlet.properties】文件中读取默认配置
       // BeanNameUrlHandlerMapping 和 RequestMappingHandlerMapping
      this.handlerMappings = getDefaultStrategies(context, HandlerMapping.class);
      if (logger.isDebugEnabled()) {
         logger.debug("No HandlerMappings found in servlet '" + getServletName() + "': using default");
      }
   }
}

适配器初始化(和映射器逻辑一致)

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.isDebugEnabled()) {
         logger.debug("No HandlerAdapters found in servlet '" + getServletName() + "': using default");
      }
   }
}

请求处理

protected void doDispatch(HttpServletRequest request, HttpServletResponse response) throws Exception {
    HttpServletRequest processedRequest = request;
    HandlerExecutionChain mappedHandler = null;
    boolean multipartRequestParsed = false;
    WebAsyncManager asyncManager = WebAsyncUtils.getAsyncManager(request);

    try {
        try {
            ModelAndView mv = null;
            Object dispatchException = null;

            try {
                processedRequest = this.checkMultipart(request);
                multipartRequestParsed = processedRequest != request;
                // 2.获取处理器映射器
                mappedHandler = this.getHandler(processedRequest);
                if (mappedHandler == null) {
                    // 获取不到handler 抛异常或者返回404
                    this.noHandlerFound(processedRequest, response);
                    return;
                }
                // 4.获取处理器适配器器
                HandlerAdapter ha = this.getHandlerAdapter(mappedHandler.getHandler());
                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;
                    }
                }
                // 6.循环调用拦截器的preHandle方法
                if (!mappedHandler.applyPreHandle(processedRequest, response)) {
                    return;
                }
                // 8.实际执行代码,handler通过反射执行控制器方法
                mv = ha.handle(processedRequest, response, mappedHandler.getHandler());
                if (asyncManager.isConcurrentHandlingStarted()) {
                    return;
                }
                //  默认视图
                this.applyDefaultViewName(processedRequest, mv);
                // 10.循环调用拦截的postHandle
                mappedHandler.applyPostHandle(processedRequest, response, mv);
            } catch (Exception var20) {
                dispatchException = var20;
            } catch (Throwable var21) {
                dispatchException = new NestedServletException("Handler dispatch failed", var21);
            }
            // 11.处理结果,进行视图解析 &  模板引擎渲染 & request域填充
            // 12.内部会调用拦截器的afterCompletion方法
            this.processDispatchResult(processedRequest, response, mappedHandler, mv, (Exception)dispatchException);
        } catch (Exception var22) {
            // 目标方法完成之后执行
            this.triggerAfterCompletion(processedRequest, response, mappedHandler, var22);
        } catch (Throwable var23) {
             // 目标方法完成之后执行
            this.triggerAfterCompletion(processedRequest, response, mappedHandler, new NestedServletException("Handler processing failed", var23));
        }

    } finally {
        if (asyncManager.isConcurrentHandlingStarted()) {
            if (mappedHandler != null) {
                mappedHandler.applyAfterConcurrentHandlingStarted(processedRequest, response);
            }
        } else if (multipartRequestParsed) {
            this.cleanupMultipart(processedRequest);
        }

    }
}


@Nullable
protected HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception {
    if (this.handlerMappings != null) {
        Iterator var2 = this.handlerMappings.iterator();

        while(var2.hasNext()) {
            HandlerMapping mapping = (HandlerMapping)var2.next();
            // 核心方法获取执行链
            HandlerExecutionChain handler = mapping.getHandler(request);
            if (handler != null) {
                return handler;
            }
        }
    }

    return null;
}


public final HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception {
    // 获取handler
    Object handler = this.getHandlerInternal(request);
    if (handler == null) {
        handler = this.getDefaultHandler();
    }
    if (handler == null) {
        // 不满足,返回
        return null;
    } else {
        if (handler instanceof String) {
            String handlerName = (String)handler;
            handler = this.obtainApplicationContext().getBean(handlerName);
        }
        // 以handler为参数获取执行链:创建一个执行链对象,handler赋值到内部变量,添加所有拦截器
        HandlerExecutionChain executionChain = this.getHandlerExecutionChain(handler, request);
        ...
        ...
        return executionChain;
    }
}


protected HandlerAdapter getHandlerAdapter(Object handler) throws ServletException {
    if (this.handlerAdapters != null) {
        Iterator var2 = this.handlerAdapters.iterator();

        while(var2.hasNext()) {
            HandlerAdapter adapter = (HandlerAdapter)var2.next();
            // 核心判断方法,找到支持该handler的适配器
            if (adapter.supports(handler)) {
                return adapter;
            }
        }
    }

    throw new ServletException("No adapter for handler [" + handler +
     "]: The DispatcherServlet configuration needs to include a HandlerAdapter that supports this handler");
}

HandlerExecutionChain#applyPreHandle

  • 拦截器的preHandle方法任意一个返回false则访问不到目标方法

  • 拦截器的afterCompletion方法一定会执行

    boolean applyPreHandle(HttpServletRequest request, HttpServletResponse response) throws Exception {
    HandlerInterceptor[] interceptors = this.getInterceptors();
    if (!ObjectUtils.isEmpty(interceptors)) {
    for(int i = 0; i < interceptors.length; this.interceptorIndex = i++) {
    HandlerInterceptor interceptor = interceptors[i];
    // 循环调用
    if (!interceptor.preHandle(request, response, this.handler)) {
    // 执行完毕拦截器的所有AfterCompletio方法后return
    this.triggerAfterCompletion(request, response, (Exception)null);
    // 一个返回false即停止循环
    return false;
    }
    }
    }
    return true;
    }

InvocableHandlerMethod#doInvoke

@Nullable
protected Object doInvoke(Object... args) throws Exception {
    ReflectionUtils.makeAccessible(this.getBridgedMethod());

    try {
        // method.invoke(obj,args);
        // 反射调用目标类的目标方法
        // 目标方法:this.getBridgedMethod()
        // this.getBean()获取handler中的bean,即为容器中的目标类实例/可能是一个CGLIB增强后的代理对象
        return this.getBridgedMethod().invoke(this.getBean(), args);
    } catch (IllegalArgumentException var4) {
        this.assertTargetBean(this.getBridgedMethod(), this.getBean(), args);
        String text = var4.getMessage() != null ? var4.getMessage() : "Illegal argument";
        throw new IllegalStateException(this.formatInvokeError(text, args), var4);
    } catch (InvocationTargetException var5) {
        Throwable targetException = var5.getTargetException();
        if (targetException instanceof RuntimeException) {
            throw (RuntimeException)targetException;
        } else if (targetException instanceof Error) {
            throw (Error)targetException;
        } else if (targetException instanceof Exception) {
            throw (Exception)targetException;
        } else {
            throw new IllegalStateException(this.formatInvokeError("Invocation failure", args), targetException);
        }
    }
}

DispatcherServlet#processDispatchResult

private void processDispatchResult(HttpServletRequest request, HttpServletResponse response, @Nullable HandlerExecutionChain mappedHandler, @Nullable ModelAndView mv, @Nullable Exception exception) throws Exception {
    boolean errorView = false;
    if (exception != null) {
        if (exception instanceof ModelAndViewDefiningException) {
            this.logger.debug("ModelAndViewDefiningException encountered", exception);
            mv = ((ModelAndViewDefiningException)exception).getModelAndView();
        } else {
            Object handler = mappedHandler != null ? mappedHandler.getHandler() : null;
            mv = this.processHandlerException(request, response, handler, exception);
            errorView = mv != null;
        }
    }

    if (mv != null && !mv.wasCleared()) {
        // a.视图解析 & 模板引擎渲染
        this.render(mv, request, response);
        if (errorView) {
            WebUtils.clearErrorRequestAttributes(request);
        }
    } else if (this.logger.isTraceEnabled()) {
        this.logger.trace("No view rendering, null ModelAndView returned.");
    }

    if (!WebAsyncUtils.getAsyncManager(request).isConcurrentHandlingStarted()) {
        if (mappedHandler != null) {
            // b.调用拦截器afterCompletion方法
            mappedHandler.triggerAfterCompletion(request, response, (Exception)null);
        }

    }
}

a.视图解析 & 模板引擎渲染

DispatcherServlet#render

protected void render(ModelAndView mv, HttpServletRequest request, HttpServletResponse response) throws Exception {
    Locale locale = this.localeResolver != null ? this.localeResolver.resolveLocale(request) : request.getLocale();
    response.setLocale(locale);
    String viewName = mv.getViewName();
    View view;
    if (viewName != null) {
        // 视图解析
        view = this.resolveViewName(viewName, mv.getModelInternal(), locale, request);
        if (view == null) {
            throw new ServletException("Could not resolve view with name '" + mv.getViewName() + "' in servlet with name '" + this.getServletName() + "'");
        }
    } else {
        view = mv.getView();
        if (view == null) {
            throw new ServletException("ModelAndView [" + mv + "] neither contains a view name nor a View object in servlet with name '" + this.getServletName() + "'");
        }
    }

    if (this.logger.isTraceEnabled()) {
        this.logger.trace("Rendering view [" + view + "] ");
    }

    try {
        if (mv.getStatus() != null) {
            response.setStatus(mv.getStatus().value());
        }
        // 模板引擎渲染
        view.render(mv.getModelInternal(), request, response);
    } catch (Exception var8) {
        if (this.logger.isDebugEnabled()) {
            this.logger.debug("Error rendering view [" + view + "]", var8);
        }

        throw var8;
    }
}

b.调用拦截器afterCompletion方法,一定会执行

HandlerExecutionChain#afterCompletion

public void triggerAfterCompletion(HttpServletRequest request, HttpServletResponse response, @Nullable Exception ex) throws Exception {
    HandlerInterceptor[] interceptors = this.getInterceptors();
    if (!ObjectUtils.isEmpty(interceptors)) {
        for(int i = this.interceptorIndex; i >= 0; --i) {
            HandlerInterceptor interceptor = interceptors[i];

            try {
                interceptor.afterCompletion(request, response, this.handler, ex);
            } catch (Throwable var8) {
                logger.error("HandlerInterceptor.afterCompletion threw exception", var8);
            }
        }
    }

}

同一路径时启动报错源码位置

AbstractHandlerMethodMapping#assertUniqueMethodMapping

private void assertUniqueMethodMapping(HandlerMethod newHandlerMethod, T mapping) {
    // 根据路径信息获取方法信息
    // 一个路径对应2个方法时第二个方法解析时会获取到上个方法的信息
   HandlerMethod handlerMethod = this.mappingLookup.get(mapping);
   // 根据路径获取到方法信息  并且  2个不是同一个方法时报错提示已经存在
   if (handlerMethod != null && !handlerMethod.equals(newHandlerMethod)) {
      throw new IllegalStateException(
            "Ambiguous mapping. Cannot map '" +    newHandlerMethod.getBean() + "' method \n" +
            newHandlerMethod + "\nto " + mapping + ": There is already '" +
            handlerMethod.getBean() + "' bean method\n" + handlerMethod + " mapped.");
   }
}