Web开发中Listener、Filter、Servlet的初始化及调用

时间:2023-03-09 03:26:02
Web开发中Listener、Filter、Servlet的初始化及调用

我们在使用Spring+SpringMVC开发项目中,web.xml中一般的配置如下:

 <?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd" version="3.0">
<!-- 加载spring配置
默认查找的配置文件位置是:WEB-INF/applicationContext.xml。
可通过下面参数指定文件位置-->
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>
classpath:applicationContext.xml
</param-value>
</context-param> <filter>
<filter-name>CorsFilter</filter-name>
<filter-class>com.filter.CORSFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>CorsFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping> <listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener> <servlet>
<servlet-name>spring-mvc</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<!-- spring mvc 默认加载的配置文件为/WEB-INF/[servlet-name]-servlet.xml,也可通过以下参数指定 -->
<!-- <init-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/spring-mvc-servlet.xml</param-value>
</init-param> -->
<!-- load-on-startup设置为1,表示项目启动时加载 -->
<load-on-startup>1</load-on-startup>
</servlet>
</web-app>

那么Listener中的contextInitialized方法是什么时候被调用呢?答案就在org.apache.catalina.core.StandardContext类的startInternal方法中

 //org.apache.catalina.core.StandardContext
@Override
protected synchronized void startInternal() throws LifecycleException {
//省略部分代码,只列出关键代码
// Configure and call application event listeners
if (ok) {
if (!listenerStart()) {
log.error(sm.getString("standardContext.listenerFail"));
ok = false;
}
} try {
// Start manager
Manager manager = getManagerInternal();
if ((manager != null) && (manager instanceof Lifecycle)) {
((Lifecycle) getManager()).start();
}
} catch(Exception e) {
log.error(sm.getString("standardContext.managerFail"), e);
ok = false;
} // Configure and call application filters
if (ok) {
if (!filterStart()) {
log.error(sm.getString("standardContext.filterFail"));
ok = false;
}
} // Load and initialize all "load on startup" servlets
if (ok) {
if (!loadOnStartup(findChildren())){
log.error(sm.getString("standardContext.servletFail"));
ok = false;
}
}

第7行执行触发listener事件,listenerStart()方法中有listener.contextInitialized(event)语句,直接调用listener的contextInitialized方法。

第27行会执行了filter的init方法,具体细节请参照tomcat源码,在此不在详细赘述。

第34行,如果在web.xml中servlet标签指定了<load-on-startup>1</load-on-startup>(值大于0即可),会执行servlet的实例化,然后调用servlet的int(ServletConfig config)。

由此也可指定在Tomcat启动时,这三者调用的先后顺序为listener-->filter-->servlet。

注:StandardContext类的startInternal方法会在Tomcat启动时调用。