SpringMVC源码 1 ContextLoaderListener和Servlet容器web.xml配置

本文深入探讨了SpringMVC中的ContextLoaderListener及其在Servlet容器web.xml配置中的作用。讲解了ServletContext的初始化过程,包括如何通过<context-param>传递参数,以及<listener>中如何创建和执行监听器。详细阐述了ContextLoaderListener的执行流程,特别是如何初始化和刷新WebApplicationContext。此外,还讨论了Spring上下文在web.xml中的配置方式,以及多个监听器和配置文件的加载顺序与差异。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

SpringMVC源码 1 ContextLoaderListener和Servlet容器web.xml配置


1.先说下ServletContext
javaee标准规定了,servlet容器需要在应用项目启动时,给应用项目初始化一个ServletContext作为公共环境容器存放公共信息。ServletContext中的信息都是由容器提供的。

通过contextListener获取web.xml中的参数。<context-param>以及<listener>
1.servlet容器启动的时候,找到应用配置文件(web.xml)中的<context-param>作为键值对放到ServletContext中。
2.servlet容器读取<listener>节点,构建对应的listener,容器调用了 contextInitialized(ServletContextEvent event)方法,执行其中的操作。(所有Listener必须继承自ServletContextListener

<context-param>只是将上下文的键值对传入servletContext中,本身并没有什么实际意义,需要Listener对参数进行解析后才具有一定意义。其中param-name是规定的,有Listener中进行定义。例如定义了m-name,在配置文件中<param-name>也需要是m-name。
<listener>  初始化上下文的监听器。    <listener>是否可以设置多个??? 答案是显然的,当然可以。

web.xml
<context-param>
     <param-name>contextConfigLocation</param-name>  //contextConfigLocation是在Spring的ContextLoader中定义的参数,确定Spring配置文件位置
     <param-value>classpath:applicationContext.xml</param-value>
</context-param>
<context-param>
     <param-name>m-name</param-name>   //m-name是在自己写的ServletContextListener实现类中定义的参数
     <param-value>mname</param-value>
</context-param>
<context-param>
     <param-name>contextId</param-name>  //contextId是在Spring的ContextLoader中定义的参数
     <param-value>MMM-WebApplicationContext</param-value>
</context-param>
//如果想要在web程序初始化的时候使用ServletContextListener,就必须在web.xml中加入<listener>节点
<listener>
     <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<listener>
     <listener-class>com.XXX.MYContextListener</listener-class>
</listener>

public class MYContextListener implements ServletContextListener{
     public static final String CONTEXT_NAME_PARAM = "m-name";
     public static final String CONTEXT_CLASS_PARAM = "m-class";
     @Override
     public void contextInitialized(ServletContextEvent sce) {
           ServletContext context = sce.getServletContext();
           String mname = (String) context.getInitParameter(CONTEXT_NAME_PARAM);
           String mclass = context.getInitParameter(CONTEXT_CLASS_PARAM);
           System.out.println(mname+"   "+mclass);
     }

     @Override
     public void contextDestroyed(ServletContextEvent sce) {
           // TODO Auto-generated method stub

     }
}

public class ContextLoaderListener extends ContextLoader implements ServletContextListener{
     ........

     @Override
     public void contextInitialized(ServletContextEvent event) {
           initWebApplicationContext(event.getServletContext());
     }

     /**Close the root web application context.*/
     @Override
     public void contextDestroyed(ServletContextEvent event) {
          closeWebApplicationContext(event.getServletContext());
          ContextCleanupListener.cleanupAttributes(event.getServletContext());
     }
}

其中spring需要的contextConfigLocation也是在spring中的ContextLoader.class中定义的
public static final String CONTEXT_ID_PARAM = "contextId";
public static final String CONFIG_LOCATION_PARAM = "contextConfigLocation";
public static final String CONTEXT_CLASS_PARAM = "contextClass";等等等等  具体看后面的源码解释。

2.执行流程
web.xml在<context-param>标签中声明应用范围内的初始化参数
1.启动一个WEB项目的时候,容器(如:Tomcat)会去读它的配置文件web.xml.读两个节点: <listener>和 <context-param>
2.紧接着,容器创建一个ServletContext(上下文)。在该应用内全局共享。
3.容器将<context-param>转化为键值对,并交给ServletContext。有接下来的ServletContextListener去调用
4.容器创建<listener>中的类实例,即创建监听.该监听器必须实现自ServletContextListener接口。 可以定义多个listener,执行顺序按照web.xml中定义的顺序来执行。
5.在Listener中会有contextInitialized(ServletContextEvent event)初始化方法
   在这个方法中获得ServletContext = ServletContextEvent.getServletContext();
  String value = ServletContext.getInitParameter("<context-param name>");
6.得到这个context-param的值之后,你就可以做一些操作了.注意,这个时候你的WEB项目还没有完全启动完成.这个动作会比所有的Servlet都要早.
换句话说,这个时候,你对<context-param>中的键值做的操作,将在你的WEB项目完全启动之前被执行.只有在这个时候<context-param>中的参数才是有意义的(也只对相应的listener而言)。对于ServletContext来说只是一组String键值对

所有的servlet容器和listener监听类,都是同意按照java Servlet API来进行开发的。Package javax.servlet

3.ContextLoaderListener 和ContextLoader

项目中使用Spring 时,applicationContext.xml配置文件中并没有BeanFactory,要想在业务层中的class 文件中直接引用Spring容器管理的bean可通过以下方式
1、在web.xml配置监听器ContextLoaderListener。ContextLoaderListener的作用就是启动Web容器时,自动装配ApplicationContext的配置信息。因为它实现了ServletContextListener这个接口,在 web.xml配置这个监听器,启动容器时,就会默认执行它实现的方法。
在ContextLoaderListener继承了ContextLoader这个类,所以整个加载配置过程由ContextLoader来完成。


ContextLoaderListener作为springMVC,在Servlet容器启动时的上下文件监听器。在servlet容器启动的时候,会调用在<listener>中定义的ContextLoaderListener,调用contextInitialzed()方法,初始化上下文。
ContextLoaderListener实现ServletConte
### SpringMVC 源码分析 #### 初始化过程 SpringMVC 的初始化主要由 `DispatcherServlet` 完成。当应用程序启动时,Web容器(如Tomcat)会加载配置文件并创建上下文环境。对于SpringMVC而言,这涉及到读取特定于web应用的配置参数以及注册监听器[^4]。 ```xml <context-param> <param-name>contextConfigLocation</param-name> <param-value>classpath:applicationContext03.xml</param-value> </context-param> <listener> <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class> </listener> ``` 上述XML片段展示了如何设置全局的应用程序上下文位置,并指定使用哪个类作为监听器来处理上下文事件。这里提到的是 `ContextLoaderListener`,它用于加载根WebApplicationContext。 #### 请求处理流程 一旦SpringMVC被成功初始化,在接收到HTTP请求之后,整个工作流如下: - **前端控制器接收请求**:所有的请求都会先到达 `DispatcherServlet` 这个前端控制器。 - **HandlerMapping映射处理器**:根据URL模式找到相应的Controller实例及其方法执行逻辑。 - **调用目标业务组件**:通过反射机制调用实际的目标方法来进行业务操作。 - **构建ModelAndView对象**:在控制层中组装好要传递给视图的数据结构——即包含了视图名模型数据的对象。 - **解析视图名称**:利用 `ViewResolver` 来查找匹配的具体视图实现类[^2]。 - **渲染页面内容**:最终选定的视图负责把之前准备好的数据转换为HTML或其他形式返回给浏览器显示[^1]。 例如下面这段代码定义了一个基于JSTL标签库的标准内部资源视图解析方式[^3]: ```xml <bean class="org.springframework.web.servlet.view.XmlViewResolver"> <property name="location"> <value>spring-views.xml</value> </property> </bean> <bean id="internalResource" class="org.springframework.web.servlet.view.JstlView"> <property name="url" value="/index.jsp"/> </bean> ``` 以上配置说明了如何通过 XML 文件中的 bean 配置项告知框架哪些视图应该关联到什么样的物理路径上;而后者则具体指定了某个 JSP 页面的位置。 另外还有一段简单的 Java 代码用来展示怎样创建一个带有消息属性 (`msg`) 视图名字 ("internalResource") 的 `ModelAndView` 实例: ```java ModelAndView mv = new ModelAndView("internalResource", "msg", "aaa"); ``` 此代码片段表明开发者可以灵活地向视图提供必要的信息以便后续呈现给用户界面。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值