servlet中ServletContainerInitializer的简单说明
根据官方文档到的说明
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的简单说明的更多相关文章
- servlet中cookie的使用
---恢复内容开始--- Cookie是存储在客户端计算机上的文本文件,并保留了它们的各种信息跟踪的目的. Java Servlet透明支持HTTP Cookie. 涉及标识返回用户有三个步骤: 服务 ...
- JSP Servlet中的Request和Response的简单研究
本文参考了几篇文章所得,参考目录如下: 1.http://www.cnblogs.com/guangshan/p/4198418.html 2.http://www.iteye.com/problem ...
- servlet中的相对路径和绝对路径 及/, ./, ../的区别
./ 当前目录../ 父级目录/ 根目录资源寻找都是依靠路径,资源存储方式是按照哈希表运算的,所以路径的计算其实就是哈希值的计算. servlet中,所有路径的配置都要用绝对路径. 什么是绝对路径,就 ...
- JSP+Servlet中使用cos.jar进行图片上传(文件上传亦然)
链接:JSP+Servlet中使用jspsmartupload.jar进行图片上传下载 关于cos.jar,百度百科只有这么几句话(http://baike.baidu.com/subview/406 ...
- JSP/Servlet 中的汉字编码问题
JSP/Servlet 中的汉字编码问题 1.问题的起源 每个国家(或区域)都规定了计算机信息交换用的字符编码集,如美国的 ASCII,中国的 GB2312 -80,日本的 JIS 等,作为该国家/区 ...
- Servlet复习1: 一个简单的Servlet的使用
Servlet学习 1. Servlet与JSP的关系 2. Servlet的声明周期 3. 一个简单的Servlet的使用方法 什么是Servlet? 什么又是JSP? 继承了javax.servl ...
- servlet中filter(过滤器)的学习使用
servlet过滤器是小型的web组件,它能够处理传入的请求和传出的响应.Filter 不是一个servlet,它不能产生一个response,它能够在一个request到达servlet之前预处理r ...
- servlet中的过滤器 国际化
1. 过滤器 基本概念 过滤器是需要在xml中配置的. 为什么需用到过滤器? 项目开发中,经常会涉及到重复代码的实现! 注册 ----à Servlet [1. 设置编码] ----à JSP 修改 ...
- JavaWeb(一)Servlet中的ServletConfig与ServletContext
前言 前面我介绍了一下什么是servlet,它的生命周期,执行过程和它的原理.这里我们做一个简单的回顾! 什么是Servlet? servlet 是运行在 Web 服务器中的小型 Java 程序(即: ...
随机推荐
- POJ 2987 Firing 最大流 网络流 dinic 模板
https://www.cnblogs.com/137shoebills/p/9100790.html http://poj.org/problem?id=2987 之前写过这道题,码一个dinic的 ...
- Unity 3d 实现物体跟随摄像机视野运动
https://blog.csdn.net/qq_31411825/article/details/61623857 Unity 3d 实现物体跟随摄像机视野运动Created by miccall ...
- Spark-Hadoop、Hive、Spark 之间是什么关系?
作者:Xiaoyu Ma链接:https://www.zhihu.com/question/27974418/answer/38965760来源:知乎著作权归作者所有.商业转载请联系作者获得授权,非商 ...
- Pytest权威教程22-优质集成实践
目录 优质集成实践 使用pip安装包 Python测试发现的约定 选择测试布局结构/导入规则 在应用程序代码外测试 测试作为应用程序代码的一部分 tox 返回: Pytest权威教程 优质集成实践 使 ...
- 比较实用的Java工具类
一. org.apache.commons.io.IOUtils closeQuietly:关闭一个IO流.socket.或者selector且不抛出异常,通常放在finally块 toString: ...
- Fluent 批量添加线面、点面、平面的scheme实现 【转载】
转载自http://chan1629.blog.163.com/blog/static/19595703220137219166686 新建一个filename.scm,文件,用记事本打开. 在文件中 ...
- etcd,flannel,docker relationship---and k8s
journalctl -xe voidcn.com/article/p-qufvdmpq-bqn.html etcd more etcd.confETCD_NAME=default ETCD_DATA ...
- Chapter Four
JSON数据 默认情况下,当开发者新创建一个SpringBoot项目时,会添加Web依赖,在这个依赖中会默认加入jackson-databind作为Json处理器. @RestController 组 ...
- MVC框架的主要问题是什么?
以下是MVC框架的一些主要问题: 对 DOM 操作的代价非常高 程序运行缓慢且效率低下 内存浪费严重 由于循环依赖性,组件模型需要围绕 models 和 views 进行创建
- (二)SpringMVC+mybatis实践
一.需求 以案例作为驱动 springmvc和mybatis使用一个案例(商品订单管理系统) 功能需求:商品的列表查询 二.环境准备 数据库环境 Java环境 jdk1.8 eclipse sprin ...