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

SpringMVC的源码解析

程序员文章站 2024-03-07 08:14:38
学习java的人都知道spring,springmvc,mybatis等框架,像structs2这样的框架是基于servlet以外实现的,而springmvc是基于serv...

学习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它们的作用。以及一个请求到处理返回,大致过程的分析。

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