zoukankan      html  css  js  c++  java
  • 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



     

     

     

     

     

     

  • 相关阅读:
    DS博客作业06--图
    DS博客作业05--树
    DS博客作业03--栈和队列
    DS博客作业02-线性表
    DS博客作业01--日期抽象数据类型设计与实现
    C语言博客作业06---结构体&文件
    C语言博客作业05---指针
    C语言博客作业04--数组
    DS博客作业08--课程总结
    DS博客作业07--查找
  • 原文地址:https://www.cnblogs.com/wqff-biubiu/p/12422393.html
Copyright © 2011-2022 走看看