import java.util.Set;
import javax.servlet.ServletContainerInitializer;
// ************** ServletContainerInitializer接口 的使用 **************
// 1、在jar包中创建META-INF/services/javax.servlet.ServletContainerInitializer文件
// 2、在文件中写入实现的类路径,如:org.apache.jasper.servlet.JasperInitializer
// ************** Tomcat中对ServletContainerInitializer接口的实现类的检测和自动调用 **************
// 检测实现ServletContainerInitializer接口的类---------------------------1
class org.apache.catalina.core.StandardContext{
protected synchronized void startInternal() throws LifecycleException {
// 读取并解析“d:/a/c/d/tomcat/conf/web.xml”,读取并解析"d:/a/b/tomcat/conf/Catalina/localhost/web.xml.default"
// 取得输入流 "d:/a/b/c/tomcat/webapps/dir1/WEB-INF/web.xml"
// 合并配置文件内容
// 合并全局配置
// 使用 org.apache.jasper.servlet.JspServlet 包装 <jsp-file>/a/b/c/file.jsp</jsp-file>的文件
// 把解析处理的内容设置到 context 中 ,如:context.addFilterMap(filterMap);
// 在org.apache.catalina.core.NamingContextListener事件处理器中,内部调用了createNamingContext()创建 envCtx
// Notify our interested LifecycleListeners 触发事件监听器 org.apache.catalina.startup.ContextConfig
fireLifecycleEvent(Lifecycle.CONFIGURE_START_EVENT, null); // 配置启动事件 "configure_start"----------------------
}
// 添加初始化器
public void addServletContainerInitializer(
ServletContainerInitializer sci, Set<Class<?>> classes) {
initializers.put(sci, classes);
}
}
class org.apache.catalina.startup.ContextConfig{
public void lifecycleEvent(LifecycleEvent event) {
context = (Context) event.getLifecycle(); // 取得触发者 org.apache.catalina.core.StandardContext
configureStart();
}
protected synchronized void configureStart() {
// 读取并解析“d:/a/c/d/tomcat/conf/web.xml”,读取并解析"d:/a/b/tomcat/conf/Catalina/localhost/web.xml.default"
// 取得输入流 "d:/a/b/c/tomcat/webapps/dir1/WEB-INF/web.xml"
// 合并配置文件内容
// 合并全局配置
// 使用 org.apache.jasper.servlet.JspServlet 包装 <jsp-file>/a/b/c/file.jsp</jsp-file>的文件
// 把解析处理的内容设置到 context 中 ,如:context.addFilterMap(filterMap);
webConfig();//!!!! 核心
}
protected void webConfig() {
// org.apache.jasper.servlet.JasperInitializer jasper.jar
// org.apache.tomcat.websocket.server.WsSci tomcat-websocket.jar
// 解析类路径中"META-INF/services/javax.servlet.ServletContainerInitializer"文件内容
// 创建文件中声明的类型对象,并把创建对象转成ServletContainerInitializer类型的引用
// initializerClassMap{
// 'MyServletContainerInitializer1_Obj'=>[],
// 'MyServletContainerInitializer2_Obj'=>[],
// }
// typeInitializerMap{
// 'MyAnnotation1.class'=>[MyServletContainerInitializer1_Obj ],
// 'MyAnnotation2.class'=>[MyServletContainerInitializer2_Obj ]
// }
processServletContainerInitializers(); // 查看实现ServletContainerInitializer的初始化器
if (ok) {
// org.apache.jasper.servlet.JasperInitializer jasper.jar
// org.apache.tomcat.websocket.server.WsSci tomcat-websocket.jar
// 解析类路径中"META-INF/services/javax.servlet.ServletContainerInitializer"文件内容
// 创建文件中声明的类型对象,并把创建对象转成ServletContainerInitializer类型的引用
// initializerClassMap{
// 'MyServletContainerInitializer1_Obj'=>[],
// 'MyServletContainerInitializer2_Obj'=>[],
// }
// typeInitializerMap{
// 'MyAnnotation1.class'=>[MyServletContainerInitializer1_Obj ],
// 'MyAnnotation2.class'=>[MyServletContainerInitializer2_Obj ]
// }
for (Map.Entry<ServletContainerInitializer,Set<Class<?>>> entry : initializerClassMap.entrySet()) {
if (entry.getValue().isEmpty()) { // 添加Servlet容器初始化器到StandardContext
// 添加初始化器
// context === org.apache.catalina.core.StandardContext
// StandardContext.initializers.put(entry.getKey(), null);
context.addServletContainerInitializer(
entry.getKey(), null);
} else {
context.addServletContainerInitializer(
entry.getKey(), entry.getValue());
}
}
}
protected void processServletContainerInitializers() {
// 容器初始化器
WebappServiceLoader<ServletContainerInitializer> loader = new WebappServiceLoader<>(context);
// org.apache.jasper.servlet.JasperInitializer jasper.jar
// org.apache.tomcat.websocket.server.WsSci tomcat-websocket.jar
// 解析类路径中"META-INF/services/javax.servlet.ServletContainerInitializer"文件内容
// 创建文件中声明的类型对象,并把创建对象转成ServletContainerInitializer类型的引用
detectedScis = loader.load(ServletContainerInitializer.class); // 检测到的 ServletContainerInitializer
for (ServletContainerInitializer sci : detectedScis) {
initializerClassMap.put(sci, new HashSet<Class<?>>()); // 要调用的初始化器
}
}
}
// 调用实现ServletContainerInitializer接口的类的方法,进行初始化---------------------------2
class org.apache.catalina.core.StandardContext{
protected synchronized void startInternal() throws LifecycleException {
// fireLifecycleEvent(Lifecycle.CONFIGURE_START_EVENT, null);
// ....
// org.apache.jasper.servlet.JasperInitializer jasper.jar
// org.apache.tomcat.websocket.server.WsSci tomcat-websocket.jar
// Call ServletContainerInitializers
for (Map.Entry<ServletContainerInitializer, Set<Class<?>>> entry :
initializers.entrySet()) { // 调用容器初始化器 ,
// 如:org.apache.jasper.servlet.JasperInitializer.onStartup();
try {
// 执行初始化器
entry.getKey().onStartup(entry.getValue(),getServletContext());
} catch (ServletException e) {
log.error(sm.getString("standardContext.sciFail"), e);
ok = false;
break;
}
}
}
}
}
Tomcat8.x 中对ServletContainerInitializer接口的实现类的检测和自动调用
最新推荐文章于 2024-04-21 07:39:16 发布