根据官方文档到的说明

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>

最新文章

  1. 移动端web开发,click touch tap区别
  2. linux 命令行中常用光标移动快捷键
  3. ZeroMQ接口函数之 :zmq_ipc – ZMQ本地进程间通信传输协议
  4. Meteor常用技能
  5. Localization要从第一天开始计划
  6. hadoop: hive 1.2.0 在mac机上的安装与配置
  7. drupal THEME主要文件
  8. 切诺夫界证明(Chernoff bound)
  9. hdu_2604Queuing(快速幂矩阵)
  10. 洛谷P1776 宝物筛选
  11. 学习笔记TF058:人脸识别
  12. puppet使用 apache passsenger 作为前端 (centos)
  13. BeautifulSoup解析器的选择
  14. VS增加插件 Supercharger破解教程
  15. Java并发编程1--synchronized关键字用法详解
  16. dart基础语法
  17. 使用.mongorc.js移除哪些比较“危险”的shell辅助函数
  18. [Git] Undo a commit that has already been pushed to the remote repository
  19. Cracking the Coding Interview(linked list)
  20. 简话Angular 02 Angular控制器-作用域嵌套

热门文章

  1. 使用apache 的 ab命令压力测试nginx服务器
  2. Ubuntu安装php7.0环境
  3. python 之 列表常用 操作
  4. 37、数据源之通用的load和save操作
  5. [golang]7种 Go 程序性能分析方法
  6. Python之☞float浮点数精度问题
  7. 割点 —— Tarjan 算法
  8. JSP带有标签体的自定义标签
  9. 解释下Http请求头和常见响应状态码
  10. Linux 文件与目录的权限