SpringMVC的源码解析

时间:2021-10-31 14:47:02

学习java的人都知道spring,springmvc,mybatis等框架,像structs2这样的框架是基于servlet以外实现的,而springmvc是基于servlet容器实现的,

本文将分析springmvc的核心分发器dispatcherservlet的初始化过程以及处理请求的过程,让读者了解这个入口servlet的作用。

在分析dispatcherservlet之前,我们先看下dispatcherservlet的继承关系,

SpringMVC的源码解析

httpserlvetbean继承自httpservlet。

httpservletbean覆写了init方法,对初始化过程做了一些处理。 以下是初始化的代码:

SpringMVC的源码解析

首先,servletconfigpropertyvalues是httpservletbean的静态类,构造过程会使用servletconfig对象找出web.xml文件中配置参数,并设置到servletconfigpropertyvalue,使用beanwrapper来构造dispatcherservlet, 获取servletcontextresourceloader的资源加载器,然后注册资源编辑器,初始化beanwrapper对象,设置dispatcherservlet属性,默认初始化servletbean不做任何处理,子类覆盖该方法可以做任何事情,

以下是web.xml文件配置:

SpringMVC的源码解析

这段配置初始化参数为contextconfiglocation,后来构造的是beanwrapper对象, 由于contextconfiglocation在frameworkservlet中定义,但是没有在httpservletbean中定义,利用spring的注入特性,只需要调用setcontextconfiglocation方法,就可以将contextconfiglocation设置到对应的实例当中,然后设置dispatcherservlet中contextconfiglocation(frameworkservlet中定义)的属性,为web.xml读取contextconfiglocation参数,该资源文件用构造springmvc的容器的上下文。

下面看下frameworkservlet这个类,frameworkservlet继承自httpservletbean。

以下是initservletbean的代码:

SpringMVC的源码解析

首先第一步是初始化webapplicationcontext,它是继承于applcationcontext的接口,applcationcontext是spring容器的上下文,servlet和spring容器关联的作用,然后初始化frameworkservlet,其实它空的,什么也做,子类重写这个方法,可以做任何处理,不过dispatcherservlet并重写这个方法。

下面是初始化initwebapplicationcontext的具体实现逻辑: 

SpringMVC的源码解析    

首先,得到根路径,distpatcherservlet有个webapplication为参数的构造函数,如果注入了webapplication 这个对象,就会执行上图代码。

SpringMVC的源码解析

frameworkservlet中有个string类型的contextattribute的变量名,以它为key在servletcontextwebapplicationcontext,一般不会设置,contextattribute属性,也就说,wac开始是null;接下来就是创建webapplicationcontext,并设置根上下文为父上下文,然后配置servletconfig,servletcontext等到这个上下文,这个类中有个函数onrefresh是一个模版方法,在webapplication成功创建后就会调用,frameworkservlet的实现类,就会重写这个方法,并将创建的容器上下文设置到servletcontext中,这里的根上下文是web.xml中配置的contextloaderlistener监听器中根据contextconfiglocation路径生成的上下文。

SpringMVC的源码解析

比如这段配置文件中根据classpath:context-*.xml下的xml文件生成的根上下文。

接着看一下dispatcherservlet重写了frameworkservlet中onrefresh方法,

SpringMVC的源码解析

可以看到initstrategies方法中,在初始化各种各种策略接口的实现类, 后面再一一分析各个策略接口的实现的详细介绍。

总结一个三个类的作用:

httpservletbean 主要做一些初始化的工作,将web.xml中配置的参数设置到servlet中。比如servlet标签的子标签init-param标签中配置的参数。

frameworkservlet 将servlet与spring容器上下文关联。其实也就是初始化frameworkservlet的属性webapplicationcontext,这个属性代表springmvc上下文,它有个父类上下文,web.xml中配置的contextloaderlistener监听器初始化的容器上下文。

dispatcherservlet 主要是初始化一些各个策略接口的实现。比如请求处理,试图处理。处理的适配等。

dispatcherservlet请求处理过程:

先看下httpservlet提供的方法用于处理请求,service使用了模版模式,对于httpservlet的get请求,调用doget方法,post请 求,调用dopost方法........

SpringMVC的源码解析

在看下处理processrequest函数

SpringMVC的源码解析

首先,获取于当前线程绑定的localecontext和servletrequestattributes对象,initcontexthoers函数就是让新构造的localecontex和requestattributes进行关联,这个关联使用threadlocal完成,doservice方法是抽象方法,具体由dispatcherservlet实现。

SpringMVC的源码解析

最后调用resetcontextholders函数重置localecontext和requestattribute对象,解除localecontext和requestattribute对象的绑定。执行成功后,发布servletrequesthandlerevent事件,可以通过注册监听器来监听该事件的发布。注册的监听器类型为applicationlistener接口类型。

接下来是dispatcherservlet的doservice方法.

SpringMVC的源码解析

如果该请求是include的请求,那么保留一份快照版本的request域中的数据,dodispatch方法之后,这个快照版本的数据将会覆盖新的requet域的数据。  

然后在request中设置一些属性,最后dodispatcher进行请求分发处理。      

dodispatch方法功能大致过程如下:

首先根据请求的路径,通过requestmapping的注解映射,找到handlermethod(也就是对应controller中的方法),然后匹配路径对应的拦截器,有了handlermethod和拦截器构造个handlerexecutionchain对象。handlerexecutionchain对象的获取是通过handlermapping接口提供的方法中得到。

有了handlerexecutionchain之后,通过handleradapter对象进行适配处理,得到modelandview对象,handlermethod内部handle的时候,使用各种handlermethodargumentresolver实现类处理handlermethod的参数,使用各种handlermethodreturnvaluehandler实现类处理返回值,最终返回值被处理成一个modelandview对象,这期间发生的异常会被handlerexceptionresolver接口实现类进行处理.

总结: 本文主要分析dispatcherservlet及其父类frameworkservlet和httpservletbean它们的作用。以及一个请求到处理返回,大致过程的分析。

以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,同时也希望多多支持服务器之家!

原文链接:http://www.cnblogs.com/xjz1842/p/6377732.html