servlet 3.0 规范
角色:应用方(spring) + servlet + web容器(tomcat)
servlet 3.0 规范
- 规范提供ServletContainerInitializer接口,应用方提供实现类。
- 规范提供"根目录/resources/META-INF/services/javax.servlet.ServletContainerInitializer"路径,应用方把ServletContainerInitializer接口实现类全类名写在该文件内。
- 规范提供@HandlesTypes注解,由应用方配置,web容器解析,解析得到的实现类集合将通过参数传给ServletContainerInitializer.onStartup方法。
- web容器启动完成回调ServletContainerInitializer.onStartup方法。
spring-web 如何实现servlet规范
spring提供WebApplicationInitializer接口,让程序员方便地进行web容器初始化回调。
spring把WebApplicationInitializer接口配置到@HandlesTypes,让web容器找到所有WebApplicationInitializer接口的实现类。
spring提供SpringServletContainerInitializer类实现ServletContainerInitializer接口,把web容器找到的实现类实例化出来,并执行。
spring把SpringServletContainerInitializer全类名配置到servlet规定的文件内,由web容器调用。
WebApplicationInitializer
public interface WebApplicationInitializer {
void onStartup(ServletContext servletContext) throws ServletException;
}
SpringServletContainerInitializer
@HandlesTypes(WebApplicationInitializer.class)
public class SpringServletContainerInitializer implements ServletContainerInitializer {
// webAppInitializerClasses:web容器找到的WebApplicationInitializer的实现类集合
@Override
public void onStartup(@Nullable Set<Class<?>> webAppInitializerClasses, ServletContext servletContext) throws ServletException {
// 执行集合
List<WebApplicationInitializer> initializers = new LinkedList<>();
if (webAppInitializerClasses != null) {
for (Class<?> waiClass : webAppInitializerClasses) {
// 验证 添加到执行集合
if (!waiClass.isInterface() && !Modifier.isAbstract(waiClass.getModifiers()) && WebApplicationInitializer.class.isAssignableFrom(waiClass)) {
try {
initializers.add((WebApplicationInitializer)ReflectionUtils.accessibleConstructor(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);
}
}
}
/resources/META-INF/services/javax.servlet.ServletContainerInitializer
org.springframework.web.SpringServletContainerInitializer
自己实现servlet 3.0 规范
CustomWebApplicationInitializer
// 参考spring的WebApplicationInitializer接口
public interface CustomWebApplicationInitializer {
void onStartup(ServletContext servletContext) throws ServletException;
}
CustomServletContainerInitializer
// 提供ServletContainerInitializer接口实现类,加上@HandlesTypes注解,传入自己提供的CustomWebApplicationInitializer接口
@HandlesTypes(CustomWebApplicationInitializer.class)
public class CustomServletContainerInitializer implements ServletContainerInitializer {
@Override
public void onStartup(Set<Class<?>> c, ServletContext ctx) throws ServletException {
List<CustomWebApplicationInitializer> initializers = new LinkedList<>();
if (c != null) {
for (Class<?> waiClass : c) {
if (!waiClass.isInterface() && !Modifier.isAbstract(waiClass.getModifiers()) && CustomWebApplicationInitializer.class.isAssignableFrom(waiClass)) {
try {
initializers.add((CustomWebApplicationInitializer) ReflectionUtils.accessibleConstructor(waiClass).newInstance());
} catch (Throwable ex) {
throw new ServletException("Failed to instantiate CustomWebApplicationInitializer class", ex);
}
}
}
}
if (initializers.isEmpty()) {
ctx.log("No Spring CustomWebApplicationInitializer types detected on classpath");
return;
}
ctx.log(initializers.size() + " Spring CustomWebApplicationInitializers detected on classpath");
AnnotationAwareOrderComparator.sort(initializers);
for (CustomWebApplicationInitializer initializer : initializers) {
initializer.onStartup(ctx);
}
}
}
/resources/META-INF/services/javax.servlet.ServletContainerInitializer
com.tbryant.springmvctest.customspringmvc.core.CustomServletContainerInitializer
使用自己实现servlet 3.0 规范
MyCustomWebApplicationInitializer
public class MyCustomWebApplicationInitializer implements CustomWebApplicationInitializer {
@Override
public void onStartup(ServletContext servletContext) {
System.out.println("web容器初始化回调,可在此添加spring容器启动代码");
}
}
其他类文件请参考spring 零xml配置 & 内置tomcat 启动spring mvc