24

【聊透SpringMVC】SpringMVC“传统”方式的启动过程

 4 years ago
source link: http://os.51cto.com/art/202003/612790.htm
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

36fyMnR.jpg!web

打成war包并放入Tomcat等Servlet容器下面运行的,都认为是SpringMVC传统的启动方式。

和SpringBoot连用且采用内嵌Web服务器并打成jar包直接运行的,可以认为是SpringMVC现代的启动方式。

传统的启动过程

基于web.xml(配置文件)的方式启动肯定算传统的,但由于现在web.xml几乎已经绝迹,所以就不考虑它了。

与之相对的就是基于编程(写代码)的方式启动,流行于前几年的SSM(Spring、SpringMVC、MyBatis)中。当然也算传统的。

在上一篇中讲到,通过一个“小桥式”的接口ServletContainerInitializer(Servlet容器初始化器)把Tomcat的启动和初始化进程带到了SpringMVC里。

在这个“桥式”接口上可以指定“感兴趣”的类或接口,SpringMVC指定的是WebApplicationInitializer(Web应用初始化器)接口,意图已经很明显,就是通过这个初始化器接口来完成SpringMVC应用的启动和初始化。

我们先来看下这个初始化接口,如下图01:

QRJnIfq.jpg!web

它只有一个onStartup方法,方法只有一个参数就是ServletContext,这个ServletContext由Tomcat创建好后提供给SpringMVC,SpringMVC在启动过程中调用这个onStartup方法,在这个方法内完成自身的创建和初始化,还要把Servlet和Filter等注册到ServletContext里。

这些工作都是SpringMVC要做的,而不是我们要做的,所以SpringMVC肯定已经实现了这个接口,我们查看下类型信息,如下图02:

YfEnmav.jpg!web

我们发现了一个看着很重要的类,就是:

AbstractAnnotationConfigDispatcherServletInitializer

可惜这个类是抽象的,肯定是不能直接用的,但是它里面已经包含了刚刚上面提到的所有完整的启动逻辑过程。

如果你对SSM很熟悉或Spring的官方文档看的很熟悉的话,你一定知道这个类是怎么用的。是的,我们需要定义一个类来继承它即可。

先看下官方文档上给的用法,如下图03:

rENfyez.jpg!web

继承之后,我们需要提供三方面信息,一个是用于注册到根容器中的类,一个是用于注册到Servlet容器中的类,一个是核心Servlet的映射URL。

注意,这里说的容器指的是Spring的ApplicationContext这个容器,其中根容器和Servlet容器是父子关系,且在SpringMVC中核心Servlet映射的URL必须是“/”。

下面给出一个我在几年前为公司搭建框架时的代码,如下图04:

fYn6JvB.jpg!web

这就是以编程的方式来完成SpringMVC的启动。我们自己定义的这个类就是前文提到的“感兴趣”的类。

这个类是不用(或不能)向Spring容器注册的,因为这个类是感兴趣的类,所以Tomcat会从jar包里把它找出来,这样SpringMVC就拿到了我们定义的这个类。

其实最主要的是这时候根本还没有Spring容器呢,哈哈,因为Spring容器就是在这个类里才创建出来的,有点意思吧。

其实这个类里包含的内容非常多,我们都可以使用写代码的方式来进行配置。下面举几个示例。

比如对核心Servlet的一些定制化设置,如下图05:

NFJ3yiZ.jpg!web

比如可以加进去一些自己需要的过滤器,如下图06:

numAfyN.jpg!web

比如可以对文件上传进行一些配置,如下图07:

3qQnEfU.jpg!web

当然,还可以介入到Spring容器的初始化过程中,进行一些额外的操作,如激活特定的Profile等,如下图08:

jUNrIz2.jpg!web

启动过程中做的事情

其实前面已经说了一些了,这里再来个完整版的,主要包括的事情有:

1、创建根容器。

2、然后把根容器放入ServletContext中。

3、接着创建Servlet容器。

4、然后使用Servlet容器去创建核心Servlet。

5、接着把核心Servlet注册到ServletContext中。

6、接着再注册一些过滤器。

下面我们使用几张图把这些内容一个个展示一下,需要详细了解的可以去看看对应的源码。

创建根容器,可以看到是基于注解的容器类,如下图09:

11ff3bd6b2a0aa21ac52160862a034f2.jpg

将根容器放入ServletContext中,因为ServletContext在应用运行期间一直存在,所以根容器是一个全局性的,也一直存在,如下图10:

a242d239c48446ad20dbefcbd548ba52.jpg

创建Servlet容器,容器类也是基于注解的,和根容器类是一样的,如下图11:

AVZFzeV.jpg!web

使用Servlet容器去创建核心Servlet,如下图12:

IJbmMf7.jpg!web

把核心Servlet注册到ServletContext中,如下图13:

b0bc3ff2582b47da3cd9216f7ed0a90f.jpg

最后就是注册一些过滤器了,如下图14:

mqqiUzM.jpg!web

号主提示:建议做Java开发且渴望优秀的朋友一定要把这些东西搞清楚。


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK