SpringMVC——DispatcherServlet

tomcat容器启动加载web.xml初始化springmvc相关策略组件

一、WebApplicationContext的层次结构

 本来是想研究一下springMVC组件的,结果解决了以前的一个疑问。WebApplicationContext的层次结构

下面是从官网copy的一份web.xml

ContextLoaderListener:初始化一个Root WebApplicationContext:SpringIOC初始化一些中间services+datasouces的Bean

DispatcherServlet:初始化一个Servlet WebApplicationContext:SpringIOC初始化前端controllers+view resovlers+HandleMapping的Bean

父子关系:Servlet WebApplicationContext.setParent(Root WebApplicationContext);子容器找不到就去父容器找。

<web-app>

    <listener>
        <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
    </listener>

    <context-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>/WEB-INF/app-context.xml</param-value>
    </context-param>

    <servlet>
        <servlet-name>app</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <init-param>
            <param-name>contextConfigLocation</param-name>
            <param-value></param-value>
        </init-param>
        <load-on-startup>1</load-on-startup>
    </servlet>

    <servlet-mapping>
        <servlet-name>app</servlet-name>
        <url-pattern>/app/*</url-pattern>
    </servlet-mapping>

</web-app>

二、DispatcherServlet初始化(Servlet生命周期init())

servlet.init()时初始化SpringIOC容器外,还有初始化了一部分SpringMVC组件

/* org.springframework.web.servlet.DispatcherServlet#initStrategies */
    protected void initStrategies(ApplicationContext context) {
        //多路解析器 文件上传 HttpServletRequest-->MultipartHttpServletRequest
        initMultipartResolver(context);
        //国际化
        initLocaleResolver(context);
        //主题
        initThemeResolver(context);
        //初始化HandleMapping容器
        initHandlerMappings(context);
        //初始化HandlerAdapters容器
        initHandlerAdapters(context);
        //初始化HandlerExceptionResolver容器
        initHandlerExceptionResolvers(context);
        //Request转viewName
        initRequestToViewNameTranslator(context);
        //初始化视图解析器
        initViewResolvers(context);
        //初始化FlashMapManager
        initFlashMapManager(context);
    }

重点看下HandlerMapping与HandlerAdapters

1、HandlerMapping:初始化mapping+拦截器interceptors

 initHandlerMappings(context):初始化HandlerMapping,

/* org.springframework.web.servlet.DispatcherServlet#initHandlerMappings */
    private void initHandlerMappings(ApplicationContext context) {
        this.handlerMappings = null;

        if (this.detectAllHandlerMappings) {//从ioc容器中获取显式设置(xml或者注解)的HandlerMapping类型的Bean
            //根据类型到 Servlet applicationContex及Root applicationContext中去查找
            //一般情况下,在项目中是不会显式的配置HandlerMapping类型的Bean的
            //所以这里会返回null
            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.
            }
        }

        if (this.handlerMappings == null) {
            //由于没有显式的配置HandlerMapping的Bean
            //此时会默认初始化从DispatcherServlet.properties中设定的3个HandlerMapping的Bean
            //org/springframework/web/servlet/DispatcherServlet.properties
            // ① org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping
            // ② springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping
            // ③ org.springframework.web.servlet.function.support.RouterFunctionMapping
            this.handlerMappings = getDefaultStrategies(context, HandlerMapping.class);
            if (logger.isTraceEnabled()) {
                logger.trace("No HandlerMappings declared for servlet '" + getServletName() +
                        "': using default strategies from DispatcherServlet.properties");
            }
        }
    }

 DispatchServlet.properties 注意标红的Bean,很眼熟

/* org/springframework/web/servlet/DispatcherServlet.properties */
/* 没有显式设置组件时,DispatcherServlet会默认初始化下面类型的Bean到容器中
 * MultijpartResolve没有默认,需要显式设置
 */
//国际化
org.springframework.web.servlet.LocaleResolver=org.springframework.web.servlet.i18n.AcceptHeaderLocaleResolver
//主题
org.springframework.web.servlet.ThemeResolver=org.springframework.web.servlet.theme.FixedThemeResolver
//HandlerMapping
org.springframework.web.servlet.HandlerMapping=
org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping,\
org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping,\ org.springframework.web.servlet.function.support.RouterFunctionMapping
//handlerAdapter org.springframework.web.servlet.HandlerAdapter=

org.springframework.web.servlet.mvc.HttpRequestHandlerAdapter,\ org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter,\ org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter,\ org.springframework.web.servlet.function.support.HandlerFunctionAdapter //HandlerExceptionResolve org.springframework.web.servlet.HandlerExceptionResolver= org.springframework.web.servlet.mvc.method.annotation.ExceptionHandlerExceptionResolver,\ org.springframework.web.servlet.mvc.annotation.ResponseStatusExceptionResolver,\ org.springframework.web.servlet.mvc.support.DefaultHandlerExceptionResolver //RequestToViewNameTranslator org.springframework.web.servlet.RequestToViewNameTranslator=org.springframework.web.servlet.view.DefaultRequestToViewNameTranslator //ViewResolver org.springframework.web.servlet.ViewResolver=org.springframework.web.servlet.view.InternalResourceViewResolver //FlashMapManager org.springframework.web.servlet.FlashMapManager=org.springframework.web.servlet.support.SessionFlashMapManager

 RequestHandlerRequestMapping:请求uri到controller方法的映射器

打断点发现RequestHandlerRequestMapping初始化后就已经存在映射关系,

 ① 然后跟踪createBean()最终发现Bean初始化最后阶段调用afterPropertiesSet()时注册映射关系,初始化mapping

/* org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping#afterPropertiesSet */
    public void afterPropertiesSet() {
        this.config = new RequestMappingInfo.BuilderConfiguration();
        this.config.setUrlPathHelper(getUrlPathHelper());
        this.config.setPathMatcher(getPathMatcher());
        this.config.setSuffixPatternMatch(useSuffixPatternMatch());
        this.config.setTrailingSlashMatch(useTrailingSlashMatch());
        this.config.setRegisteredSuffixPatternMatch(useRegisteredSuffixPatternMatch());
        this.config.setContentNegotiationManager(getContentNegotiationManager());
        //注册RequestMapping
        super.afterPropertiesSet();
    }

/* org.springframework.web.servlet.handler.AbstractHandlerMethodMapping#afterPropertiesSet */

    public void afterPropertiesSet() {
        initHandlerMethods();
    }

    protected void initHandlerMethods() {
        //getCandidateBeanNames()获取所有实例化的Bean,
        //注意:DispatcherServlet.initStrategies()是在IOC容器初始化完成后
        for (String beanName : getCandidateBeanNames()) {
            //过滤scopedTarget.开头的Bean
            if (!beanName.startsWith(SCOPED_TARGET_NAME_PREFIX)) {
                //扫描@Controller或者@RequestMapping注解的类
                //扫描@RequestMapping注解的方法
                //注册到映射关系到对应容器中(url-RequestMappingInfo)
                processCandidateBean(beanName);
            }
        }
        //不可修改视图+打印日志
        handlerMethodsInitialized(getHandlerMethods());
    }

    protected void processCandidateBean(String beanName) {
        Class<?> beanType = null;
        try {
            //获取beanType
            beanType = obtainApplicationContext().getType(beanName);
        }
        catch (Throwable ex) {
            // An unresolvable bean type, probably from a lazy bean - let's ignore it.
            if (logger.isTraceEnabled()) {
                logger.trace("Could not resolve type for bean '" + beanName + "'", ex);
            }
        }
        //检查beanType不为空
        //并且beanType被@Controller或者@RequestMapping注解
        if (beanType != null && isHandler(beanType)) {
            detectHandlerMethods(beanName);
        }
    }

    protected void detectHandlerMethods(Object handler) {
        //重新获取beanType == handlerType
        Class<?> handlerType = (handler instanceof String ?
                obtainApplicationContext().getType((String) handler) : handler.getClass());

        if (handlerType != null) {
            Class<?> userType = ClassUtils.getUserClass(handlerType);
            //获取映射关系<Method , RequestMappingInfo>
            Map<Method, T> methods = MethodIntrospector.selectMethods(userType,
                    (MethodIntrospector.MetadataLookup<T>) method -> {
                        try {
                            //selectMethods中查找beanType的所有方法
                            //然后遍历method,getMappingForMethod获取@RequestMapping信息生成一个RequestMappingInfo实例
                            //重点RequestMappingInfo.path=Controller的@RequestMapping.value+Method的@RequestMaping.value
                            //然后生成映射关系<method,RequestMappingInfo>
                            return getMappingForMethod(method, userType);
                        }
                        catch (Throwable ex) {
                            throw new IllegalStateException("Invalid mapping on handler class [" +
                                    userType.getName() + "]: " + method, ex);
                        }
                    });
            if (logger.isTraceEnabled()) {
                logger.trace(formatMappings(userType, methods));
            }
            //注册映射关系
            methods.forEach((method, mapping) -> {
                Method invocableMethod = AopUtils.selectInvocableMethod(method, userType);
                //注册映射关系到RequestMapHandlerMapping.mappingRegistry的五个容器中
                //mappingRegistry的类型:org.springframework.web.servlet.handler.AbstractHandlerMethodMapping.MappingRegistry
                //5个容器全部是Map类型
                //urlLookup.add(url, mapping);
                //mappingLookup.put(mapping, handlerMethod);
                //corsLookup.put(handlerMethod, corsConfig);
                //registry.put(mapping, new MappingRegistration<>(mapping, handlerMethod, directUrls, name));
                //nameLookup.put(name, newList);newList=List<handlerMethod>
                //handlerMethod就是beanName、beanType、beanFactory、method、parameters的封装
                //其实就是url -> mapping -> handlerMethod ->invoke
                registerHandlerMethod(handler, invocableMethod, mapping);
            });
        }
    }

② 初始化拦截器interceptors

其实初始化拦截器还要在初始化mapping之前,回忆一下bean初始化

/* org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#initializeBean(java.lang.String, java.lang.Object, org.springframework.beans.factory.support.RootBeanDefinition) */
    protected Object initializeBean(final String beanName, final Object bean, @Nullable RootBeanDefinition mbd) {
        ...
        if (mbd == null || !mbd.isSynthetic()) {
            //调用所有BeanPostProcessor前置方法
            //这里初始化拦截器interceptors
            wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
        }

        try {
            //调用afterPropertiesSet() 这里 初始化mapping
            invokeInitMethods(beanName, wrappedBean, mbd);
        }
        ...
    }        

调用ApplicaitonContextAwareProcessor.postProcessorBeforeInitialization(),实现拦截器初始化,最终走到下面:

/* org.springframework.web.servlet.handler.AbstractHandlerMapping#initApplicationContext */
    protected void initApplicationContext() throws BeansException {
        extendInterceptors(this.interceptors);
        detectMappedInterceptors(this.adaptedInterceptors);
        initInterceptors();
    }

此时RequestHandlerRequestMapping初始化完成:

2、RequestMappingHandlerAdapter

 ① 同RequestHandlerRequestMapping一样,也是afterPropertiesSet()方法中完成注册,而且更加直接

    public void afterPropertiesSet() {
        // Do this first, it may add ResponseBody advice beans
        initControllerAdviceCache();
        //参数类型解析器(总共注册了20+个解析器)
        //重点关注:ServletModelAttributeMethodProcessor,后面会用到
        if (this.argumentResolvers == null) {
            List<HandlerMethodArgumentResolver> resolvers = getDefaultArgumentResolvers();
            this.argumentResolvers = new HandlerMethodArgumentResolverComposite().addResolvers(resolvers);
        }
        //参数类型赋值器(总共注册了10+个解析器)
        if (this.initBinderArgumentResolvers == null) {
            List<HandlerMethodArgumentResolver> resolvers = getDefaultInitBinderArgumentResolvers();
            this.initBinderArgumentResolvers = new HandlerMethodArgumentResolverComposite().addResolvers(resolvers);
        }
        //返回参数类型解析器(总共注册了10+个解析器)
        if (this.returnValueHandlers == null) {
            List<HandlerMethodReturnValueHandler> handlers = getDefaultReturnValueHandlers();
            this.returnValueHandlers = new HandlerMethodReturnValueHandlerComposite().addHandlers(handlers);
        }
    }

三、DispatcherServlet服务(Servlet生命周期servlet.service(request,response))

DispatcherServlet的流程:FrameworkServlet.service()-->httpServlet.service()-->FrameworkServlet.doGet()-->FrameworkServlet.processRequest-->DispatcherServlet.doService()-->DispatcherServlet.doDispatch()

直接从doDispatch()开始:springmvc执行流程。

/* org.springframework.web.servlet.DispatcherServlet#doDispatch */
    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 {
                //检查是否是文件上传请求
                //是则转换为multipartRequest
                processedRequest = checkMultipart(request);
                multipartRequestParsed = (processedRequest != request);

                // 确定当前请求的处理程序
                //① 根据request中url确定执行方法methodHandler
                //② 根据request中url确定拦截器interceptors
                mappedHandler = getHandler(processedRequest);
                if (mappedHandler == null) {
                    noHandlerFound(processedRequest, response);
                    return;
                }

                // 确定当前请求的处理程序的适配器,通常是RequestMappingHandlerAdapter 
// 默认的四个适配器分别匹配
// HttpRequestHandlerAdapter: handler instanceof HttpRequestHandler // SimpleControllerHandlerAdapter:handler instanceof Controller // RequestMappingHandlerAdapter:handler instanceof HandlerMethod // HandlerFunctionAdapter:handler instanceof HandlerFunction 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; } } // 执行拦截器前置方法 // interceptor.preHandle // interceptor.preHandle没通过调用interceptor.afterCompletion然后直接返回 if (!mappedHandler.applyPreHandle(processedRequest, response)) { return; } // 实例调用程序,mappedHandler.getHandlder == MethodHandler即已经可以找到执行的controller和执行的method
// Adapter发挥作用的地方
request.parameter转化为method的参数类型 // 然后执行方法 mv = ha.handle(processedRequest, response, mappedHandler.getHandler()); if (asyncManager.isConcurrentHandlingStarted()) { return; } //viewNameTranslator applyDefaultViewName(processedRequest, mv); //拦截器后置方法 //interceptor.postHandle 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); } // handlerExceptionResolvers //异常会执行interceptor.afterCompletion processDispatchResult(processedRequest, response, mappedHandler, mv, dispatchException); } catch (Exception ex) { //异常会执行interceptor.afterCompletion triggerAfterCompletion(processedRequest, response, mappedHandler, ex); } catch (Throwable err) { //异常会执行interceptor.afterCompletion triggerAfterCompletion(processedRequest, response, mappedHandler, new NestedServletException("Handler processing failed", err)); } finally { if (asyncManager.isConcurrentHandlingStarted()) { // Instead of postHandle and afterCompletion // 异步处理时,用interceptor释放资源 // AsyncHandlerInterceptor.afterConcurrentHandlingStarted if (mappedHandler != null) { mappedHandler.applyAfterConcurrentHandlingStarted(processedRequest, response); } } else { //清除multipartResolver使用的所有资源 if (multipartRequestParsed) { cleanupMultipart(processedRequest); } } } }
mv = ha.handle(processedRequest, response, mappedHandler.getHandler()):实际controller.method调用
AbstractHandlerMethodAdapter.handle()-->RequestMappingHandlerAdapter.handleInternal()-->RequestMappingHandlerAdapter.invokeHandlerMethod()-->
ServletInvocableHandlerMethod.invokeAndHandle()
public void invokeAndHandle(ServletWebRequest webRequest, ModelAndViewContainer mavContainer,
            Object... providedArgs) throws Exception {
        //在RequestMappingHandlerAdapter.argumentResolvers的26个解析器中选择1个合适的解析器
        // resolver.supportsParameter(parameter)判断哪一个合适
        // 然后request.param --> method.param
        // 例如xxx(User user)时选择ServletModelAttributeMethodProcessor
        // 最后调用方法执行
        Object returnValue = invokeForRequest(webRequest, mavContainer, providedArgs);
        setResponseStatus(webRequest);

        if (returnValue == null) {
            if (isRequestNotModified(webRequest) || getResponseStatus() != null || mavContainer.isRequestHandled()) {
                disableContentCachingIfNecessary(webRequest);
                mavContainer.setRequestHandled(true);
                return;
            }
        }
        else if (StringUtils.hasText(getResponseStatusReason())) {
            mavContainer.setRequestHandled(true);
            return;
        }

        mavContainer.setRequestHandled(false);
        Assert.state(this.returnValueHandlers != null, "No return value handlers");
        try {
            //在RequestMappingHandlerAdapter.returnValueHandlers的15个解析器中选择1个合适的解析器
            // handler.supportsReturnType(returnType)判断哪一个合适
            // 然后method.result --> response.param,
            // 例如返回@ResponseBody返回json时选择RequestResponseBodyMethodProcessor
            // 最后返回
            this.returnValueHandlers.handleReturnValue(
                    returnValue, getReturnValueType(returnValue), mavContainer, webRequest);
        }
        catch (Exception ex) {
            if (logger.isTraceEnabled()) {
                logger.trace(formatErrorForReturnValue(returnValue), ex);
            }
            throw ex;
        }
    }

1



 

 

 

 

 

 

posted on 2020-03-05 20:15  FFStayF  阅读(272)  评论(0编辑  收藏  举报