欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

SpringMVC 源码解析

程序员文章站 2024-02-07 15:15:04
前言 年初面试时接触到一道面试题,在聊到SpringMVC时提到了SpringMVC的开发者为何要设计父子容器呢,又或者说是父子容器的设计有什么更实际的作用呢? 首先要理解对于一个web应用,当其部署在web容器上时,容器会为其提供一个全局上下文环境ServletContext,这个上下文环境将为后 ......

前言

        年初面试时接触到一道面试题,在聊到springmvc时提到了springmvc的开发者为何要设计父子容器呢,又或者说是父子容器的设计有什么更实际的作用呢?
         首先要理解对于一个web应用,当其部署在web容器上时,容器会为其提供一个全局上下文环境servletcontext,这个上下文环境将为后续的spring提供宿主环境。

springmvc工作流程

SpringMVC 源码解析

dispatcherservlet上下文继承关系

SpringMVC 源码解析

springmvc设计的父子容器

父子容器配置文件

--在web.xml中配置,两个重要的xml:applicationcontext.xml和springmvc-conf.xml
<context-param>
    <param-name>contextconfiglocation</param-name>
    <param-value>classpath*:applictioncontext.xml</param-value>
</context-param>
<listener>
   <listener-class>org.springframework.web.context.contextloaderlistener</listener-class>
</listener>
  
<servlet>
    <servlet-name>dispatcher-servlet</servlet-name>
    <servlet-class>org.springframework.web.servlet.dispatcherservlet</servlet-class>
    <init-param>
      <param-name>contextconfiglocation</param-name>
      <param-value>classpath*:springmvc-conf.xml</param-value>
    </init-param>
</servlet>
  
<servlet-mapping>
  <servlet-name>dispatcher-servlet</servlet-name>
  <url-pattern>/*</url-pattern>
</servlet-mapping>

父子容器的设计目的

     根据springmvc的官方解释,父(根)容器主要包括一些基础脚手架的bean,比如pool、datasource、dao、service。目的是在不同的servlet实例之间共享。这些不同的bean可以在子容器中重写。
     而子容器主要包括一些controller、view等一些web相关的bean。 

dispatcherservlet源码分析

     既然springmvc中同时包含spring容器和springmvc容器,那么这两个容器都是在什么时候初始化呢?

根容器初始化

      首先,根容器是通过servletcontext监听器进行创建,默认的监听器为contextloaderlistener,当web应用启动时,会调用监听器的contextinitialized方法。
      那么根容器的初始化就从contextloaderlistener类说起吧,,spring官方对该类的描述是启动监听器去启动和关闭spring的root webapplicationcontext(翻译的实在有点蹩脚)。
     SpringMVC 源码解析

public class contextloaderlistener extends contextloader implements servletcontextlistener {
    public contextloaderlistener() {
    }

    public contextloaderlistener(webapplicationcontext context) {
        super(context);
    }

    //===初始化root webapplicationcontext===
    @override
    public void contextinitialized(servletcontextevent event) {
        initwebapplicationcontext(event.getservletcontext());
    }

    @override
    public void contextdestroyed(servletcontextevent event) {
        closewebapplicationcontext(event.getservletcontext());
        contextcleanuplistener.cleanupattributes(event.getservletcontext());
    }
}

   

//contextloader.java
public webapplicationcontext initwebapplicationcontext(servletcontext servletcontext) {
    //初始化spring容器时如果发现servlet 容器中已存在根spring容根器则抛出异常,证明rootwebapplicationcontext只能有一个。
    if (servletcontext.getattribute(webapplicationcontext.root_web_application_context_attribute) != null) {
        throw new illegalstateexception(
                "cannot initialize context because there is already a root application context present - " +
                "check whether you have multiple contextloader* definitions in your web.xml!");
    }

    try {
        //创建webapplicationcontext实例
        if (this.context == null) {
            this.context = createwebapplicationcontext(servletcontext);
        }
        if (this.context instanceof configurablewebapplicationcontext) {
            configurablewebapplicationcontext cwac = (configurablewebapplicationcontext) this.context;
            if (!cwac.isactive()) {
                if (cwac.getparent() == null) {
                    applicationcontext parent = loadparentcontext(servletcontext);
                    cwac.setparent(parent);
                }
                //配置webapplicationcontext
                configureandrefreshwebapplicationcontext(cwac, servletcontext);
            }
        }
        
        /**
           把生成的webapplicationcontext设置成root webapplicationcontext。保存在servletcontext上下文中。
           下一步初始化mvc applicationcontext时需要从servletcontext取出根上下文作为其父上下文。
        **/ 
        servletcontext.setattribute(webapplicationcontext.root_web_application_context_attribute, this.context);

        classloader ccl = thread.currentthread().getcontextclassloader();
        if (ccl == contextloader.class.getclassloader()) {
            currentcontext = this.context;
        }
        else if (ccl != null) {
            currentcontextperthread.put(ccl, this.context);
        }
        
        return this.context;
    }
    catch (runtimeexception | error ex) {
        servletcontext.setattribute(webapplicationcontext.root_web_application_context_attribute, ex);
        throw ex;
    }
}

      以上代码主要完成两个功能:创建实例webapplicationcontext实例、把所创建的webapplicationcontext设置为根上下文,也就是设置成为root_web_application_context_attribute的值。

mvc容器初始化 

      大家知道servlet生命周期都是从init方法开始,desctory方法结束,由jvm负责垃圾回收。而dispatcherservlet也是一个普通的servlet,先看一下dispatcherservlet的继承关系图,对整个继承关系有个了解。
SpringMVC 源码解析
   既然说起servlet,那就从servlet的初始化(init)方法入手

//httpservletbean.java
@override
public final void init() throws servletexception {

    propertyvalues pvs = new servletconfigpropertyvalues(getservletconfig(), this.requiredproperties);
    if (!pvs.isempty()) {
        try {
            beanwrapper bw = propertyaccessorfactory.forbeanpropertyaccess(this);
            resourceloader resourceloader = new servletcontextresourceloader(getservletcontext());
            bw.registercustomeditor(resource.class, new resourceeditor(resourceloader, getenvironment()));
            initbeanwrapper(bw);
            bw.setpropertyvalues(pvs, true);
        }
        catch (beansexception ex) {
            throw ex;
        }
    }

    //交给子类重写
    initservletbean();
}

//frameworkservlet.java
@override
protected final void initservletbean() throws servletexception {
    try {
        this.webapplicationcontext = initwebapplicationcontext();
        initframeworkservlet();
    }
    catch (servletexception | runtimeexception ex) {
        throw ex;
    }
}

//frameworkservlet.java
//初始化mvc容器
protected webapplicationcontext initwebapplicationcontext() {
    //从servletcontext取出根上下文
    webapplicationcontext rootcontext =
            webapplicationcontextutils.getwebapplicationcontext(getservletcontext());
    webapplicationcontext wac = null;

    if (this.webapplicationcontext != null) {
        wac = this.webapplicationcontext;
        if (wac instanceof configurablewebapplicationcontext) {
            configurablewebapplicationcontext cwac = (configurablewebapplicationcontext) wac;
            if (!cwac.isactive()) {
                if (cwac.getparent() == null) {
                    cwac.setparent(rootcontext);
                }
                configureandrefreshwebapplicationcontext(cwac);
            }
        }
    }
    if (wac == null) {
        wac = findwebapplicationcontext();
    }
    
    //如果还没有webapplicatioincontext,创建webapplicationcontext
    if (wac == null) {
        wac = createwebapplicationcontext(rootcontext);
    }

    //子类自定义对servlet子上下文后续操作,在dispatcherservlet中实现
    if (!this.refresheventreceived) {
        synchronized (this.onrefreshmonitor) {
            //执行子类扩展方法onrefresh,在dispatcherservlet内初始化所有web相关组件
            onrefresh(wac);
        }
    }

    //发布servlet子上下文到servletcontext
    if (this.publishcontext) {
        string attrname = getservletcontextattributename();
        //将servlet子上下文以org.springframework.web.servlet.frameworkservlet.context. + servletname的属性名称注册到servletcontext中
        getservletcontext().setattribute(attrname, wac);
    }

    return wac;
}

protected webapplicationcontext createwebapplicationcontext(@nullable webapplicationcontext parent) {
    return createwebapplicationcontext((applicationcontext) parent);
}

protected webapplicationcontext createwebapplicationcontext(@nullable applicationcontext parent) {
    //获取webapplicationcontext实现类,此处其实就是xmlwebapplicationcontext
    class<?> contextclass = getcontextclass();
    if (!configurablewebapplicationcontext.class.isassignablefrom(contextclass)) {
        throw new applicationcontextexception("fatal initialization error in servlet with name '" + getservletname() +
                "': custom webapplicationcontext class [" + contextclass.getname() +
                "] is not of type configurablewebapplicationcontext");
    }
    
    //生成xmlwebapplicationcontext实例
    configurablewebapplicationcontext wac =
            (configurablewebapplicationcontext) beanutils.instantiateclass(contextclass);

    wac.setenvironment(getenvironment());
    //设置根容器为父容器 
    wac.setparent(parent);
    string configlocation = getcontextconfiglocation();
    if (configlocation != null) {
        //设置配置文件
        wac.setconfiglocation(configlocation);
    }
    
    //配置webapplicationcontext
    configureandrefreshwebapplicationcontext(wac);

    return wac;
}

protected void configureandrefreshwebapplicationcontext(configurablewebapplicationcontext wac) {
    if (objectutils.identitytostring(wac).equals(wac.getid())) {
        if (this.contextid != null) {
            wac.setid(this.contextid);
        }
        else {
            wac.setid(configurablewebapplicationcontext.application_context_id_prefix + objectutils.getdisplaystring(getservletcontext().getcontextpath()) + '/' + getservletname());
        }
    }

    wac.setservletcontext(getservletcontext());
    wac.setservletconfig(getservletconfig());
    wac.setnamespace(getnamespace());
    wac.addapplicationlistener(new sourcefilteringlistener(wac, new contextrefreshlistener()));

    configurableenvironment env = wac.getenvironment();
    if (env instanceof configurablewebenvironment) {
        ((configurablewebenvironment) env).initpropertysources(getservletcontext(), getservletconfig());
    }

    postprocesswebapplicationcontext(wac);
    applyinitializers(wac);
    
    //开始处理bean
    wac.refresh();
}

      上面的关键代码都在frameworkservlet类中,有几个关键点:取除根上下文,创建子上下文并设置父上下文,完成刷新,把子上下文发布到servletcontext中。 到这里可以说子容器(子上下文)已经创建完成。 并把其他初始化web组件的相关工作交给onrefresh方法完成,由dispatcherservlet来重写onrefresh方法,这就又回到了我们熟悉的initstrategies方法。

web组件初始化

 

@override
protected void onrefresh(applicationcontext context) {
    initstrategies(context);
}

protected void initstrategies(applicationcontext context) {
    //文件上传解析器
    initmultipartresolver(context);
    
    //本地化解析器
    initlocaleresolver(context);
    
    //主题解析器
    initthemeresolver(context);
    
    //处理器映射器(url和controller方法的映射)
    inithandlermappings(context);
    
    //处理器适配器(实际执行controller方法)
    inithandleradapters(context);
    
    //处理器异常解析器
    inithandlerexceptionresolvers(context);
    
    //requesttoviewname解析器
    initrequesttoviewnametranslator(context);
    
    //视图解析器(视图的匹配和渲染)
    initviewresolvers(context);
    
    //flashmap管理者
    initflashmapmanager(context);
}

             这里我们主要关注一下三个重要组件:handlermapping、handleradapter、viewresolver。分析这3个组件之前,我们先看一下我们的springmvc-conf.xml配置文件,mvc的配置文件中,我们配置了两行代码:

<context:component-scan base-package="com.zhangfei"/>
<mvc:annotation-driven>

      第二行代码主要是添加了默认的handlemapping,viewresolver,handleadapter。我们看看annotation-driven的源码定义,根据spring自定义schema定义,我们找到如下代码,如图所示:
SpringMVC 源码解析
该文件就一行代码:

http\://www.springframework.org/schema/mvc=org.springframework.web.servlet.config.mvcnamespacehandler
//mvc所有的标签解析器都定义在此
public class mvcnamespacehandler extends namespacehandlersupport {
    @override
    public void init() {
        registerbeandefinitionparser("annotation-driven", new annotationdrivenbeandefinitionparser());
        registerbeandefinitionparser("default-servlet-handler", new defaultservlethandlerbeandefinitionparser());
        registerbeandefinitionparser("interceptors", new interceptorsbeandefinitionparser());
        registerbeandefinitionparser("resources", new resourcesbeandefinitionparser());
        registerbeandefinitionparser("view-controller", new viewcontrollerbeandefinitionparser());
        registerbeandefinitionparser("redirect-view-controller", new viewcontrollerbeandefinitionparser());
        registerbeandefinitionparser("status-controller", new viewcontrollerbeandefinitionparser());
        registerbeandefinitionparser("view-resolvers", new viewresolversbeandefinitionparser());
        registerbeandefinitionparser("tiles-configurer", new tilesconfigurerbeandefinitionparser());
        registerbeandefinitionparser("freemarker-configurer", new freemarkerconfigurerbeandefinitionparser());
        registerbeandefinitionparser("groovy-configurer", new groovymarkupconfigurerbeandefinitionparser());
        registerbeandefinitionparser("script-template-configurer", new scripttemplateconfigurerbeandefinitionparser());
        registerbeandefinitionparser("cors", new corsbeandefinitionparser());
    }
}

那么通过分析annotationdrivenbeandefinitionparser类,主要完成以下三大组件的装配工作:
SpringMVC 源码解析

初始化处理器映射器

private void inithandlermappings(applicationcontext context) {
    this.handlermappings = null;

    //这里detectallhandlermappings默认值为true,可以通过配置文件设置为false
    if (this.detectallhandlermappings) {
        //从上下文(包含父上下文)中查找所有handlermapping实现类
        map<string, handlermapping> matchingbeans =
                beanfactoryutils.beansoftypeincludingancestors(context, handlermapping.class, true, false);
        if (!matchingbeans.isempty()) {
            this.handlermappings = new arraylist<>(matchingbeans.values());
            annotationawareordercomparator.sort(this.handlermappings);
        }
    }
    else {
        try {
            //这里只取固定的bean
            handlermapping hm = context.getbean(handler_mapping_bean_name, handlermapping.class);
            this.handlermappings = collections.singletonlist(hm);
        }
        catch (nosuchbeandefinitionexception ex) {
            
        }
    }
    
    /***
      确保至少有一个handlermapping,如果没能找到,注册一个默认的
      默认规则在dispatcherservlet.properties中,这里也就是取beannameurlhandlermapping、requestmappinghandlermapping
    ***/
    if (this.handlermappings == null) {
        this.handlermappings = getdefaultstrategies(context, handlermapping.class);     
    }
}

初始化处理器适配器

private void inithandleradapters(applicationcontext context) {
    this.handleradapters = null;

    if (this.detectallhandleradapters) {
        //从上下文(包括父上下文)中查找所有handleradapter实现类
        map<string, handleradapter> matchingbeans =beanfactoryutils.beansoftypeincludingancestors(context, handleradapter.class, true, false);
        if (!matchingbeans.isempty()) {
            this.handleradapters = new arraylist<>(matchingbeans.values());
            annotationawareordercomparator.sort(this.handleradapters);
        }
    }
    else {
        try {
            //这里取bean名字为handleradapter,类型为handleradapter的处理器适配器
            handleradapter ha = context.getbean(handler_adapter_bean_name, handleradapter.class);
            this.handleradapters = collections.singletonlist(ha);
        }
        catch (nosuchbeandefinitionexception ex) {
            
        }
    }
    
    /**
    如果没找到,则从默认规则里取出指定的三个实现类:httprequesthandleradapter、simplecontrollerhandleradapter、requestmappinghandleradapter
    **/
    if (this.handleradapters == null) {
        this.handleradapters = getdefaultstrategies(context, handleradapter.class);     
    }
}

初始化试图解析器

private void initviewresolvers(applicationcontext context) {
    this.viewresolvers = null;

    if (this.detectallviewresolvers) {
        //从上下文(包括父上下文)中查找所有viewresolver实现类
        map<string, viewresolver> matchingbeans =beanfactoryutils.beansoftypeincludingancestors(context, viewresolver.class, true, false);
        if (!matchingbeans.isempty()) {
            this.viewresolvers = new arraylist<>(matchingbeans.values());
            annotationawareordercomparator.sort(this.viewresolvers);
        }
    }
    else {
        try {
            viewresolver vr = context.getbean(view_resolver_bean_name, viewresolver.class);
            this.viewresolvers = collections.singletonlist(vr);
        }
        catch (nosuchbeandefinitionexception ex) {
            
        }
    }
    
    /**
    如果没找到,则从默认规则里取出指定的实现类:internalresourceviewresolver
    **/
    if (this.viewresolvers == null) {
        this.viewresolvers = getdefaultstrategies(context, viewresolver.class); 
    }
}

         三大组件的初始化最后判断为null时都会调用getdefaultstrategies方法,也就是从dispatcherservlet.properties中取出指定默认值。

protected <t> list<t> getdefaultstrategies(applicationcontext context, class<t> strategyinterface) {
    string key = strategyinterface.getname();
    string value = defaultstrategies.getproperty(key);
    if (value != null) {
        string[] classnames = stringutils.commadelimitedlisttostringarray(value);
        list<t> strategies = new arraylist<>(classnames.length);
        for (string classname : classnames) {
            try {
                class<?> clazz = classutils.forname(classname, dispatcherservlet.class.getclassloader());
                object strategy = createdefaultstrategy(context, clazz);
                strategies.add((t) strategy);
            }
            catch (classnotfoundexception ex) {
                throw new beaninitializationexception("could not find dispatcherservlet's default strategy class [" + classname +"] for interface [" + key + "]", ex);
            }
            catch (linkageerror err) {
                throw new beaninitializationexception("unresolvable class definition for dispatcherservlet's default strategy class [" +classname + "] for interface [" + key + "]", err);
            }
        }
        return strategies;
    }
    else {
        return new linkedlist<>();
    }
}

dispatcherservlet请求处理过程

     提到请求处理过程,我们再来回顾一下servlet生命周期,处理请求都放在service方法中处理,那么也从dispatcherservlet的service方法入手。dispatcherservlet继承frameworkservlet,在frameworkservlet中重写了service、doget、dopost、doput、dodelete方法。

//frameworkservlet.java
@override
protected void service(httpservletrequest request, httpservletresponse response)
        throws servletexception, ioexception {
    httpmethod httpmethod = httpmethod.resolve(request.getmethod());
    if (httpmethod == httpmethod.patch || httpmethod == null) {
        processrequest(request, response);
    }
    else {
        super.service(request, response);
    }
}

    
@override
protected final void doget(httpservletrequest request, httpservletresponse response)
        throws servletexception, ioexception {
    processrequest(request, response);
}

    
@override
protected final void dopost(httpservletrequest request, httpservletresponse response)
        throws servletexception, ioexception {
    processrequest(request, response);
}

    
@override
protected final void doput(httpservletrequest request, httpservletresponse response)
        throws servletexception, ioexception {
    processrequest(request, response);
}

    
@override
protected final void dodelete(httpservletrequest request, httpservletresponse response)
        throws servletexception, ioexception {
    processrequest(request, response);
}


protected final void processrequest(httpservletrequest request, httpservletresponse response)
            throws servletexception, ioexception {

    long starttime = system.currenttimemillis();
    throwable failurecause = null;

    localecontext previouslocalecontext = localecontextholder.getlocalecontext();
    localecontext localecontext = buildlocalecontext(request);

    requestattributes previousattributes = requestcontextholder.getrequestattributes();
    servletrequestattributes requestattributes = buildrequestattributes(request, response, previousattributes);

    webasyncmanager asyncmanager = webasyncutils.getasyncmanager(request);
    asyncmanager.registercallableinterceptor(frameworkservlet.class.getname(), new requestbindinginterceptor());
    
    //把新构造的localecontext对象和servletrequestattributes对象和当前请求线程绑定(后面要解除绑定)
    initcontextholders(request, localecontext, requestattributes);

    try {
        //抽象方法,交给dispatcherservlet方法实现
        doservice(request, response);
    }
    catch (servletexception | ioexception ex) {
        failurecause = ex;
        throw ex;
    }
    catch (throwable ex) {
        failurecause = ex;
        throw new nestedservletexception("request processing failed", ex);
    }

    finally {
        //重置localecontext和requestattributes对象,也就是解除localecontext对象和servletrequestattributes对象和当前请求线程的绑定
        resetcontextholders(request, previouslocalecontext, previousattributes);
        if (requestattributes != null) {
            requestattributes.requestcompleted();
        }
        //发布servletrequesthandledevent事件
        publishrequesthandledevent(request, response, starttime, failurecause);
    }
}
//dispatcherservlet.java
@override
protected void doservice(httpservletrequest request, httpservletresponse response) throws exception {
    
    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));
            }
        }
    }
    
    //在当前request对象中填充4个属性
    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()) {
            if (attributessnapshot != null) {
                restoreattributesafterinclude(request, attributessnapshot);
            }
        }
    }
}


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);
            
            //调用handlermapping获取handlerchain
            mappedhandler = gethandler(processedrequest);
            if (mappedhandler == null) {
                nohandlerfound(processedrequest, response);
                return;
            }

            //获取支持该handler解析的handleradapter
            handleradapter ha = 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;
                }
            }

            if (!mappedhandler.applyprehandle(processedrequest, response)) {
                return;
            }

            //使用handleradapter完成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) {
            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()) {
            if (mappedhandler != null) {
                mappedhandler.applyafterconcurrenthandlingstarted(processedrequest, response);
            }
        }
        else {
            if (multipartrequestparsed) {
                cleanupmultipart(processedrequest);
            }
        }
    }
}

        dispatcherservlet的dodispatch方法概括起来大致就是以下几点:首先根据当前请求路径找到对应的handlermethod,一个handlermethod和若干个拦截器构造一个handlerexecutionchain.通过handlerexecutionchain得到handleradapter对象通过执行handleradapter的handle方法得到modelandview对象,调用modelandview解析视图,渲染视图,response结束。

参考



https://www.cnblogs.com/fangjian0423/p/springmvc-dispatcherservlet.html