根据官方文档到的说明

public interface ServletContainerInitializer
Interface which allows a library/runtime to be notified of a web application's startup phase and perform any required programmatic
registration of servlets, filters, and listeners in response to it. Implementations of this interface may be annotated with HandlesTypes, in order to receive (at their onStartup(java.util.Set>,
javax.servlet.ServletContext) method) the Set of application classes that implement, extend, or have been annotated with the class types specified by the annotation. If an implementation of this interface does not use this annotation, or none of the application classes match the ones specified
by the annotation, the container must pass a null Set of classes to onStartup(java.util.Set>, javax.servlet.ServletContext). When examining the classes of an application to see if they match any of the criteria specified by the HandlesTypes annotation
of a ServletContainerInitializer, the container may run into classloading problems if any of the application's optional JAR files
are missing. Because the container is not in a position to decide whether these types of classloading failures will prevent the
application from working correctly, it must ignore them, while at the same time providing a configuration option that would log them. Implementations of this interface must be declared by a JAR file resource located inside the META-INF/services directory
and named for the fully qualified class name of this interface, and will be discovered using the runtime's service provider lookup
mechanism or a container specific mechanism that is semantically equivalent to it. In either case, ServletContainerInitializer
services from web fragment JAR files excluded from an absolute ordering must be ignored, and the order in which these services
are discovered must follow the application's classloading delegation model.

在容器启动的时候,他会去加载META-INF/services/javax.servlet.ServletContainerInitializer文件下指定的实现类

demo:

创建文件

里面的内容是实现了javax.servlet.ServletContainerInitializer的自定义类,并重写它的方法

@HandlesTypes(value = {HelloService.class})
public class MyServletContainerInitializer implements ServletContainerInitializer {
@Override
public void onStartup(Set<Class<?>> set, ServletContext servletContext) throws ServletException {
for(Class clazz : set){
System.out.println("获取的class..."+clazz);
}
}
}
@HandlesTypes 可以获取到指定类型的所有子
Set<Class<?>> set获取到的class
servletContext servlet上下文
创建HelloService一个子类型:

启动程序,看打印结果:
获取的class...class com.servlet.HelloServiceImp
获取的class...class com.servlet.AbstractHelloService
在加载的时候,onStartup()方法执行时,我们也可以加入自定义的servlet,filter,listener
        servletContext.addServlet("userServlet",UserServlet.class).addMapping("/user");

            servletContext.addListener(Mylistener.class);

            servletContext.addFilter("userFilter",userFilter.class).addMappingForUrlPatterns(EnumSet.of(DispatcherType.REQUEST),true,"/*");

在springmvc中,web容器启动到的时候也会去加载META-INF/services/javax.servlet.ServletContainerInitializer,加载指定的类

SpringServletContainerInitializer

来看看SpringServletContainerInitializer这个类

@HandlesTypes(WebApplicationInitializer.class)
public class SpringServletContainerInitializer implements ServletContainerInitializer {
@Override
public void onStartup(Set<Class<?>> webAppInitializerClasses, ServletContext servletContext)
throws ServletException { List<WebApplicationInitializer> initializers = new LinkedList<WebApplicationInitializer>(); if (webAppInitializerClasses != null) {
for (Class<?> waiClass : webAppInitializerClasses) {
// Be defensive: Some servlet containers provide us with invalid classes,
// no matter what @HandlesTypes says...
if (!waiClass.isInterface() && !Modifier.isAbstract(waiClass.getModifiers()) &&
WebApplicationInitializer.class.isAssignableFrom(waiClass)) {
try {
initializers.add((WebApplicationInitializer) waiClass.newInstance());
}
catch (Throwable ex) {
throw new ServletException("Failed to instantiate WebApplicationInitializer class", ex);
}
}
}
} if (initializers.isEmpty()) {
servletContext.log("No Spring WebApplicationInitializer types detected on classpath");
return;
} servletContext.log(initializers.size() + " Spring WebApplicationInitializers detected on classpath");
AnnotationAwareOrderComparator.sort(initializers);
for (WebApplicationInitializer initializer : initializers) {
initializer.onStartup(servletContext);
}
} }
@HandlesTypes(WebApplicationInitializer.class)这和servlet中的操作一样,他会去获取到WebApplicationInitializer的子类型

WebApplicationInitializer下三个抽象类:
AbstractContextLoaderInitializer:创建根容器createRootApplicationContext()
@Override
public void onStartup(ServletContext servletContext) throws ServletException {
registerContextLoaderListener(servletContext);
}
protected void registerContextLoaderListener(ServletContext servletContext) {
WebApplicationContext rootAppContext = createRootApplicationContext();
if (rootAppContext != null) {
ContextLoaderListener listener = new ContextLoaderListener(rootAppContext);
listener.setContextInitializers(getRootApplicationContextInitializers());
servletContext.addListener(listener);
}
else {
logger.debug("No ContextLoaderListener registered, as " +
"createRootApplicationContext() did not return an application context");
}
}
AbstractDispatcherServletInitializer:
  1、创建web的ioc容器createServletApplicationContext()
  2、创建DispatcherServlet:createDispatcherServlet(servletAppContext)
    添加到ServletContext中:servletContext.addServlet(servletName, dispatcherServlet)
@Override
public void onStartup(ServletContext servletContext) throws ServletException {
super.onStartup(servletContext);
registerDispatcherServlet(servletContext);
} protected void registerDispatcherServlet(ServletContext servletContext) {
String servletName = getServletName();
Assert.hasLength(servletName, "getServletName() must not return empty or null"); WebApplicationContext servletAppContext = createServletApplicationContext();
Assert.notNull(servletAppContext,
"createServletApplicationContext() did not return an application " +
"context for servlet [" + servletName + "]"); FrameworkServlet dispatcherServlet = createDispatcherServlet(servletAppContext);
dispatcherServlet.setContextInitializers(getServletApplicationContextInitializers()); ServletRegistration.Dynamic registration = servletContext.addServlet(servletName, dispatcherServlet);
Assert.notNull(registration,
"Failed to register servlet with name '" + servletName + "'." +
"Check if there is another servlet registered under the same name."); registration.setLoadOnStartup();
registration.addMapping(getServletMappings());
registration.setAsyncSupported(isAsyncSupported()); Filter[] filters = getServletFilters();
if (!ObjectUtils.isEmpty(filters)) {
for (Filter filter : filters) {
registerServletFilter(servletContext, filter);
}
} customizeRegistration(registration);
}
AbstractAnnotationConfigDispatcherServletInitializer:

    创建根容器:createRootApplicationContext(),它覆写了上面的方法,获取RootConfigClasses类的配置
    创建web的ioc容器:createServletApplicationContext() ,它覆写了上面的方法,获取ServletConfigClasses类的配置
@Override
protected WebApplicationContext createRootApplicationContext() {
Class<?>[] configClasses = getRootConfigClasses();
if (!ObjectUtils.isEmpty(configClasses)) {
AnnotationConfigWebApplicationContext rootAppContext = new AnnotationConfigWebApplicationContext();
rootAppContext.register(configClasses);
return rootAppContext;
}
else {
return null;
}
}
@Override
protected WebApplicationContext createServletApplicationContext() {
AnnotationConfigWebApplicationContext servletAppContext = new AnnotationConfigWebApplicationContext();
Class<?>[] configClasses = getServletConfigClasses();
if (!ObjectUtils.isEmpty(configClasses)) {
servletAppContext.register(configClasses);
}
return servletAppContext;
}
写一个类MyWebAppInitializer来继承AbstractAnnotationConfigDispatcherServletInitializer
public class MyWebAppInitializer extends AbstractAnnotationConfigDispatcherServletInitializer {

    @Override
protected Class<?>[] getRootConfigClasses() {
return new Class<?>[] { RootConfig.class };
} @Override
protected Class<?>[] getServletConfigClasses() {
return new Class<?>[] { App1Config.class };
} @Override
protected String[] getServletMappings() {
return new String[] { "/app1/*" };
}
}

写配置类RootConfig:它不去扫描controller,controller交给App1Config扫描

@ComponentScan(value = "com.springmvc",excludeFilters = {@ComponentScan.Filter(type = FilterType.ANNOTATION,classes = {Controller.class})})
public class RootConfig {
}

写配置类App1Config:

@ComponentScan(value = "com.springmvc",includeFilters = {@ComponentScan.Filter(type= FilterType.ANNOTATION,classes = {Controller.class})})
public class App1Config {
}
这是使用注解来实现配置,用web.xml文件来配置:
<web-app>

    <listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener> <context-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/root-context.xml</param-value>
</context-param> <servlet>
<servlet-name>app1</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/app1-context.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet> <servlet-mapping>
<servlet-name>app1</servlet-name>
<url-pattern>/app1/*</url-pattern>
</servlet-mapping> </web-app>

servlet中ServletContainerInitializer的简单说明的更多相关文章

  1. servlet中cookie的使用

    ---恢复内容开始--- Cookie是存储在客户端计算机上的文本文件,并保留了它们的各种信息跟踪的目的. Java Servlet透明支持HTTP Cookie. 涉及标识返回用户有三个步骤: 服务 ...

  2. JSP Servlet中的Request和Response的简单研究

    本文参考了几篇文章所得,参考目录如下: 1.http://www.cnblogs.com/guangshan/p/4198418.html 2.http://www.iteye.com/problem ...

  3. servlet中的相对路径和绝对路径 及/, ./, ../的区别

    ./ 当前目录../ 父级目录/ 根目录资源寻找都是依靠路径,资源存储方式是按照哈希表运算的,所以路径的计算其实就是哈希值的计算. servlet中,所有路径的配置都要用绝对路径. 什么是绝对路径,就 ...

  4. JSP+Servlet中使用cos.jar进行图片上传(文件上传亦然)

    链接:JSP+Servlet中使用jspsmartupload.jar进行图片上传下载 关于cos.jar,百度百科只有这么几句话(http://baike.baidu.com/subview/406 ...

  5. JSP/Servlet 中的汉字编码问题

    JSP/Servlet 中的汉字编码问题 1.问题的起源 每个国家(或区域)都规定了计算机信息交换用的字符编码集,如美国的 ASCII,中国的 GB2312 -80,日本的 JIS 等,作为该国家/区 ...

  6. Servlet复习1: 一个简单的Servlet的使用

    Servlet学习 1. Servlet与JSP的关系 2. Servlet的声明周期 3. 一个简单的Servlet的使用方法 什么是Servlet? 什么又是JSP? 继承了javax.servl ...

  7. servlet中filter(过滤器)的学习使用

    servlet过滤器是小型的web组件,它能够处理传入的请求和传出的响应.Filter 不是一个servlet,它不能产生一个response,它能够在一个request到达servlet之前预处理r ...

  8. servlet中的过滤器 国际化

    1. 过滤器 基本概念 过滤器是需要在xml中配置的. 为什么需用到过滤器? 项目开发中,经常会涉及到重复代码的实现! 注册 ----à Servlet [1. 设置编码] ----à  JSP 修改 ...

  9. JavaWeb(一)Servlet中的ServletConfig与ServletContext

    前言 前面我介绍了一下什么是servlet,它的生命周期,执行过程和它的原理.这里我们做一个简单的回顾! 什么是Servlet? servlet 是运行在 Web 服务器中的小型 Java 程序(即: ...

随机推荐

  1. 阿里开源线上应用调试利器 Arthas的背后

    Arthas是一个功能非常强大的诊断工具,功能点很多,例如:jvm信息.线程信息.搜索类中的方法.跟踪代码执行.观测方法的入参和返回参数等等. 作为有追求的程序员,你不仅要知道它能做什么,更要思考它是 ...

  2. linux 查看内存,free,ps,说明Buffers,Cached,SReclaimable

    查看机器剩余内存free即可,百度就可以轻松查到,主要想说的 查所有进程占用内存情况并排序: ps aux | sort -nk5 k5代表根据RSS排序,k6代表VSZ排序. ----------- ...

  3. SSM 整合 ehcache spring 配置文件报错

    添加 <!-- end MyBatis使用ehcache缓存 --> <cache:annotation-driven cache-manager="cacheManage ...

  4. js判断是不是在微信浏览器打开?

    is_weixin:function(){      var ua = window.navigator.userAgent.toLowerCase();      if (ua.match(/Mic ...

  5. 数组不能用for each ,

    数组不能用for each 不能用这 for(String xkz:xkzzj){ SjshdcDTO sjshdcDTO = cpcyService.findSjshdcDTOById(xkz); ...

  6. 数据库blob图片文件,多图片打包下载

    数据库存储blob图片文件,前端打包下载 数据库图片文件实体类 package com.cmrh.mspserver.pos.dto; import java.io.Serializable; imp ...

  7. SQLEXPR_x64_CHS、SQLEXPRADV_x64_CHS、SQLEXPRWT_x64_CHS、SqlLocalDB、SQLManagementStudio_x64_CHS各版本说明

    LocalDB (SqlLocalDB)LocalDB 是 Express的一种轻型版本,该版本具备所有可编程性功能,但在用户模式下运行,并且具有快速的零配置安装和必备组件要求较少的特点.如果您需要通 ...

  8. C/C++/Linux编程经典电子书pdf下载

    实际上目前Linux下C开发一般都是C++实现下的C,而不是最纯粹的C,使用g++而不是gcc编译,所以直接学习C++的过程性C部分是更加高效的. C++ Primer(中文版 第5版)C++学习头牌 ...

  9. gcov—a Test Coverage Program

    gcov—a Test Coverage Program https://coverage.readthedocs.io/en/v4.5.x/cmd.html 覆盖率测试

  10. 浏览器cookie数 跨站请求伪造 欧盟Cookie指令

    <?php for ($w=0; $w < 200 ; $w++) { setcookie('name'.$w,'value'.$w, time()+3600*10 ); } var_du ...