tomcat + spring mvc 原理(一):tomcat原理综述和静态架构
- tomcat + spring mvc的运作模式
- tomcat内部的基本容器构成
- tomcat容器对应的外部配置
tomat + spring mvc 是目前比较流行java微服务体系架构,包括现在的spring boot以及基于spring boot的进一步应用化封装的spring cloud框架,底层都是基于tomcat + spring mvc的框架。因此学习tomcat + spring mvc的基础原理,对于解决使用中出现的问题会有比较大的帮助。
tomcat + spring mvc的运作模式
理解tomcat+spring mvc的工作原理之前,最好能自己配置一下tomcat环境,然后部署一个spring mvc服务,实际感受一下整个流程,对tomcat和spring mvc暴露在外的配置有一个大概的了解。这样有了感性的认识之后,再深入了解原理,会有比较好的理解。网上已经有很多比较详细的关于tomcat环境搭建的文章,这里我就不再赘述。
传统的使用tomcat + spring mvc框架的服务在开发之前,需要先行配置tomcat的环境。这个过程包括下载和安装tomcat,配置环境变量,修改tomcat的配置文件,最后运行tomcat。对,你没看错,tomcat独立运行,而spring mvc的服务是tomcat运行时加载的。基于spring mvc框架的服务可以在流行的java IDE中自动创建,比如eclipse或者idea。自动创建的工程基本配置已经写入,你可以直接动手书写业务代码,这也是这种架构的显著优势。当然你也可以创建一个空的项目,自行配置。总的来说,spring mvc基于xml或者java代码的config文件的配置是比较繁琐的。项目最后需要打包成一个war文件,复制到tomcat的指定目录下,tomcat会自动解包加载,然后基于你的配置,访问指定端口的指定路由链接,就可以请求服务器的信息应答。
显然,这种运作模式要求:tomcat需要有监视指定目录,一旦有新的war包加入,就完成解包并动态加载编译后的class的能力;tomcat需要有网络端口开闭和监视的机制,维护线程池来处理随时可能到来的请求;tomcat还需要将到来的请求顺利地传递给spring mvc服务,然后再将服务返回的数据发送出去。
tomcat内部的基本容器构成
所谓容器(Container),并不是常说的用来存储数据结构的类,比如Collection、Set、List等,而是专指tomcat和spring mvc中用来对功能和结构进行分层抽象的概念(类或者接口)。tomcat的基本容器结构如图所示:
tomcat最顶层的容器Server,代表整个tomcat服务器,一个Server可以包含一个或者多个Service。一个Service包含一个或者多个Connetor,但是只能包含一个Container。Connector主要用来处理连接相关的事,比如网络套接字Socket的监听、请求request的接收和应答response的发送。这里的Container是一个抽象的概念,一个接口。其实是指一个Service只能包含一个Engine–Engine继承自Container。Engine容器结构如图所示:
其中Engine、Host、Context和Wrapper都继承自Container。
Engine用来管理多个站点,即可以有多个Host。Host代表一个站点,其实是一个虚拟主机。Context,上下文,代表一套应用程序,一套应用程序总是有相同的应用上下文配置。最后是Wrapper,每个wrapper只有一个Servlet,而每个Servlet即对应每个开发的spring mvc服务程序。所以我们开发的spring mvc服务程序都是通过Wrapper加载到tomcat中。Context和Wrapper是动态添加的,我们在tomcat的指定目录下每添加一个war包,tomcat加载war包时,就可以添加Context和Servlet。
tomcat容器对应的外部配置
之所以强调学习原理之前,最好先自己配置tomcat环境和部署一个spring mvc服务程序,是因为tomcat的很多配置和内部容器相关。外部感性理解和对内部原理的理性理解的结合,有益于认知的深入和记忆。
在tomcat的安装目录下(使用linux yum安装的默认目录在/usr/local/tomcat下,其他系统和安装方法的目录需要百度),有一个conf文件夹,里面存放着一些tomcat层次的容器配置。server.xml配置了Server容器下Service、Connector、Engine和Host的配置,格式类似上图所显示的嵌套结构,不过是以xml的形式。以其中一个Connector配置为例:
<Connector port="8080" protocol="HTTP/1.1"
connectionTimeout="20000"
redirectPort="8443" />
上面说到Connector主要用来处理连接相关的事,比如网络套接字Socket的监听、请求request的接收和应答response的发送。所以这里就配置了端口、网络协议、连接超时时间和重定向端口。其他容器的配置也比较类似,可以自行打开浏览一下。conf目录下的context.xml文件存放Context容器的配置:
<Context>
<!-- Default set of monitored resources. If one of these changes, the -->
<!-- web application will be reloaded. -->
<WatchedResource>WEB-INF/web.xml</WatchedResource>
<WatchedResource>${catalina.base}/conf/web.xml</WatchedResource>
<!-- Uncomment this to disable session persistence across Tomcat restarts -->
<!--
<Manager pathname="" />
-->
</Context>
内部主要包括了两个web.xml的目录配置。按照上文所讲的容器结构,Context容器可以中可以有一个或者多个Wrapper,每个Wrapper中包含一个Servlet,Servlet就是我们开发的spring mvc 服务程序。web.xml里写的是spring mvc Servlet的相关配置,一般的spring mvc项目中会有一个WEB-INF目录,内部包含一个自己配置的web.xml文件。另一个是tomcat默认的web.xml的配置,可以看到就是conf目录下的web.xml,这个默认配置是针对所有部署在tomcat中的spring mvc程序。具体关于web.xml配置内容的解释,放在后面的spring mvc原理综述中。