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 程序(即: ...
随机推荐
- C利用time函数实现简单的定时器
//定时器 #include <stdio.h> #include <time.h> #include <stdlib.h> int main(int num, c ...
- comobox在datagrid里,当滚动scrollbar时,会导致comobox选中项被重置的解决办法
VirtualizingStackPanel.IsVirtualizing="False"
- ZR#1012
## ZR#1012 blog咕咕咕了好久,开始补. 解法: 一个很显然的性质, $ x $ 只能转移到 $ x+1 $ 或者 $ 2x $ 处,所以我们可以以此性质建图,即 $ x $ 向 $ x ...
- 2018-2019 20165226 Exp 8 Web基础
2018-2019 20165226 Exp 8 Web基础 目录 一.实验内容说明及基础问题回答 二.实验过程 1.Web前端:HTML 2.Web前端j:avascipt 3.Web后端:MySQ ...
- C#作业处理
2019.9.8 作业要求: 将字符串加密,即将字符串中每个字符向后移动五个字符,并输出密文 解决方案: using System; using System.Collections.Generic; ...
- 文献阅读 | Benchmarking single cell RNA-sequencing analysis pipelines using mixture control experiments
资源: sci-hub paper CellBench package - github CellBench_data - code for the paper 现在单细胞领域的突出问题就是工具过多, ...
- Ionic4.x ion-infinite-scroll 上拉分页加载更多
<ion-header> <ion-toolbar> <ion-title> Tab One </ion-title> </ion-toolbar ...
- pytorch 计算图像数据集的均值和标准差
在使用 torchvision.transforms进行数据处理时我们经常进行的操作是: transforms.Normalize((0.485,0.456,0.406), (0.229,0.224, ...
- oracle11g 查询临时表空间的使用率和正在使用临时表空间的用户
转: oracle11g 查询临时表空间的使用率和正在使用临时表空间的用户 原创 Oracle 作者:记录每一次错误 时间:2018-12-21 15:46:33 11179 0 今天开发反映说临时表 ...
- windows下新增项目本地通过git bash推送至远程github
本地E盘workspace目录下新增了spring-cloud-alibaba-demo项目,还没有编译过,没有target等不需要推送至git的文件,所以就直接用git bash丢到github了. ...