ServletContainerInitializer机制

2018-12-27 09:48:29

ServletContainerInitializer

  • Servlet3.0的特性
  • 主要功能就是在容器启动的时候,通过编程的方式去注册Servlet Filter Listenner等组件,代替web.xml
  • 容器启动会扫描应用所有的jar目录下的META-INF/services/javax.servlet.ServletContainerInitializer文件
  • 该文件的内容就是ServletContainerInitializer实现类的全类名
  • 容器会自动创建它的实例,并且调用接口方法onStartup
  • 可以给实现类添加注解@HandlesTypes,通过该注解指定感兴趣的类。容器会把系统中指定类的所有子类通过方法参数Set<Class<?>> c。传递进来。

Demo

新建工程,实现ServletContainerInitializer

创建 META-INF/services/javax.servlet.ServletContainerInitializer文件

新建一个web项目 & 添加该依赖 & 测试

启动web项目,initializer 成功执行

SpringBoot的实现

SpringServletContainerInitializer

  1. import java.lang.reflect.Modifier;
  2. import java.util.LinkedList;
  3. import java.util.List;
  4. import java.util.ServiceLoader;
  5. import java.util.Set;
  6. import javax.servlet.ServletContainerInitializer;
  7. import javax.servlet.ServletContext;
  8. import javax.servlet.ServletException;
  9. import javax.servlet.annotation.HandlesTypes;
  10. import org.springframework.core.annotation.AnnotationAwareOrderComparator;
  11. import org.springframework.lang.Nullable;
  12. import org.springframework.util.ReflectionUtils;
  13. @HandlesTypes(WebApplicationInitializer.class) //感兴趣的是所有 WebApplicationInitializer 的子类
  14. public class SpringServletContainerInitializer implements ServletContainerInitializer {
  15. @Override
  16. public void onStartup(@Nullable Set<Class<?>> webAppInitializerClasses, ServletContext servletContext)throws ServletException {
  17. List<WebApplicationInitializer> initializers = new LinkedList<>();
  18. if (webAppInitializerClasses != null) {
  19. for (Class<?> waiClass : webAppInitializerClasses) {
  20. // 子类不是接口,不是抽象类,并且是 WebApplicationInitializer 的子类
  21. if (!waiClass.isInterface() && !Modifier.isAbstract(waiClass.getModifiers()) && WebApplicationInitializer.class.isAssignableFrom(waiClass)) {
  22. try {
  23. //实例化
  24. initializers.add((WebApplicationInitializer)ReflectionUtils.accessibleConstructor(waiClass).newInstance());
  25. }
  26. catch (Throwable ex) {
  27. throw new ServletException("Failed to instantiate WebApplicationInitializer class", ex);
  28. }
  29. }
  30. }
  31. }
  32. if (initializers.isEmpty()) {
  33. servletContext.log("No Spring WebApplicationInitializer types detected on classpath");
  34. return;
  35. }
  36. servletContext.log(initializers.size() + " Spring WebApplicationInitializers detected on classpath");
  37. // 排序
  38. AnnotationAwareOrderComparator.sort(initializers);
  39. for (WebApplicationInitializer initializer : initializers) {
  40. // 初始化
  41. initializer.onStartup(servletContext);
  42. }
  43. }
  44. }
  • SpringBootWar形式部署项目的时候,需要实现接口SpringBootServletInitializer
  • SpringBootServletInitializer就是WebApplicationInitializer的子类
  • 也就是说,系统启动的时候,Servlet容器就会加载我们的SpringBootServletInitializer实现。
  • 这样就实现了SpringBootWar形式的编程配置

1
3
0

添加评论

正在回复:
取消
0
1
3
0