Spring如何与Tomcat框架进行集成

一、前言

本节我们讲究如何利用Tomcat的ContextLoaderListener扩展接口来把Spring框架与Tomcat进行连接起来。

二、ContextLoaderListener扩展接口

ContextLoaderListener一般用来启动一个Spring容器或者框架的根容器,例如Webx框架的WebxContextLoaderListener就是继承该类,实现了webx框架到Tomcat容器的衔接点,而SpringMVC则通过在ContextLoaderListener启动一个IOC来管理bo类的bean,下面首先看下ContextLoaderListener的类图结构:640?wx_fmt=png可知ContextLoaderListener的两个方法都是含有一个ServletContextEvent类型的参数。

那么这个ContextLoaderListener一般是怎么使用的那?ContextLoaderListener一般是按照下面的方式配置到web.xml里面:640?wx_fmt=png

如上代码,首先创建了一个ContextLoaderListener实例,该实例会创建一个XmlWebApplicationContext应用程序上下文,contextConfigLocation是要告诉ContextLoaderListener要把哪些Bean注入到XmlWebApplicationContext管理的BeanFactory。

这里首先有几个问题,比如配置的全局的contextConfigLocation属性是怎么在ContextLoaderListener中获取的?ContextLoaderListener与Tomcat是什么关系那?ContextLoaderListener是如何创建的XmlWebApplicationContext?

为了解开前两个问题,我们需要看下Tomcat(本文tomcat版本为 apache-tomcat-8.5.12)中的一些代码时序图640?wx_fmt=png

  • 在Tomcat中一个StandardContext代表者一个Web应用,时序图中步骤(2)(3)在Web应用启动过程中会调用mergeParameters方法解析web.xml配置的context-param参数,并把这些参数设置到ApplicationContext中,也就是说上面配置的contextConfigLocation参数和值也保存到了ApplicationContext中,需要注意的是这里的ApplicationContext不同于Spring框架中的ApplicationContext,这里的ApplicationContext是tomcat中的ApplicationContext ,它实现了 org.apache.catalina.servlet4preview.ServletContext,是一个ServletContext,这个ApplicationContext是应用级别的,每个应用维护着自己的一个ApplicationContext对象,用来保存应用级别的变量信息,其内部通过 privatefinalConcurrentMap<String,String>parameters=newConcurrentHashMap<>();保存应用级别的变量信息。

  • 时序图中步骤(4)(5)(6)是初始化所有在web.xml里面配置的ServletContextListener的实现类,并以ApplicationContext为构造函数参数创建一个ServletContextEvent 作为ServletContext事件(内部实际维护的是ApplicationContext的一个门面类ApplicationContextFacade),然后调用所有实现类的contextInitialized的方法并传递ServletContextEvent作为参数,至此解开了ContextLoaderListener与Tomcat的关系,也就是说在tomcat的每个应用启动过程中会调用ContextLoaderListener的contextInitialized方法并且传递的参数里面包含该应用级别的一个ApplicationContext对象,该对象里面包含了该应用的全局作用域的变量集合。

下面看下ContextLoaderListener的contextInitialized方法时序图,看是如何创建XmlWebApplicationContext并获取到了contextConfigLocation变量的值作为Spring容器加载Bean的数据源:

640?wx_fmt=png

  • 如上时序图步骤(3)创建Spring应用程序上下文XmlWebApplicationContext

  • 如上时序图步骤(5)设置XmlWebApplicationContext的ServletContext为ApplicationContextFacade

  • 如上时序图步骤(6)(7)从ServletContext中获取contextConfigLocation变量的值,这里为WEB-INF/applicationContext.xml

  • 如上时序图步骤(8)设置XmlWebApplicationContext的配置文件为WEB-INF/applicationContext.xml,这意味着会从WEB-INF/applicationContext.xml中解析Bean注入到XmlWebApplicationContext管理的BeanFactory。

  • 如上时序图步骤(9)刷新XmlWebApplicationContext应用程序上下文

  • 如上时序图步骤(10)保存XmlWebApplicationContext到ServletContext,这样应用里面任何有ServletContext的地方就可以获取XmlWebApplicationContext,从而可以获取XmlWebApplicationContext管理的所有Bean。

三、 SpringMVC与Tomcat容器的衔接点

SpringMvc是目前使用非常频繁的框架,springmvc里面经常会使用两级级联容器,并且每层容器都各有用途,使用过SpringMVC的童鞋都知道,一般我们在web.xml里面会配置一个listener和一个dispatcher,其实这就配置了两个spring IOC容器,并且dispatcher容器的父容器就是listener的容器。一般在web.xml里面配置如下:

&lt;listener&gt;	
    &lt;listener-class&gt;org.springframework.web.context.ContextLoaderListener&lt;/listener-class&gt;	
&lt;/listener&gt;	
&lt;context-param&gt;	
    &lt;param-name&gt;contextConfigLocation&lt;/param-name&gt;	
    &lt;param-value&gt;WEB-INF/applicationContext.xml&lt;/param-value&gt;	
&lt;/context-param&gt;
&lt;servlet&gt;	
    &lt;servlet-name&gt;springmvc&lt;/servlet-name&gt;	
    &lt;servlet-class&gt;org.springframework.web.servlet.DispatcherServlet&lt;/servlet-class&gt;	
    &lt;load-on-startup&gt;1&lt;/load-on-startup&gt;	
&lt;/servlet&gt;

其中ContextLoaderListener会创建一个XMLWebApplicationContext上下文来管理contextConfigLocation配置的xml里面的普通bean,这个上节已经讲过。

DispatcherServlet也会创建一个XMLWebApplicationContext默认管理web-info/springmvc-servlet.xml里面的Controller bean,下面看下创建的流程时序图:640?wx_fmt=png

如图在DispatcherServlet的初始化方法中首先从ServletContext的全局变量表里面获取ContextLoaderListener创建的XMLWebApplicationContext上下文,然后使用该context作为父上下文创建了SpringMVC的servlet的context容器,并且设置namespace为springmvc-servlet,这个在查找配置文件时候用到,最后会拼接为springmvc-servlet.xml,最后刷新SpringMVC的servlet的context上下文。

一般我们在listener创建的父容器里面配置bo类用来具体操作业务,在dispatcher子容器里面配的Controller类,然后Controller里面具体调用bo类来实现业务。

至此结合上节通过Tomcat启动过程中调用ContextLoaderListener的contextInitialized方法首先创建了父容器用来管理bo bean,然后使用DispatcherServlet创建了子容器用来管理Controller bean ,ContextLoaderListener让SpringMVC与Tomcat容器联系起来了。

四、参考

  • https://docs.spring.io/spring/docs/4.3.13.RELEASE/spring-framework-reference/html/beans.html

  • https://docs.spring.io/spring/docs/4.3.13.RELEASE/spring-framework-reference/html/beans.html#beans-factory-extension

  • 4
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值