Servlet 3.0 新特性

Servlet 3.0 文档下载:https://jcp.org/aboutJava/communityprocess/mrel/jsr315/index.html

Servlet 3.0 新特性:Shared library(共享库) / runtimes pluggability (运行时插件能力)

  • Servlet 容器启动时会扫描当前应用每个 jar 包里面的 ServletContainerInitializer 的实现
  • 在应用路径下创建一个 META-INF/services/javax.servlet.ServletContainerInitializer 文件,文件中存放 ServletContainerInitializer 实现类全限定类名

即容器在启动时,会扫描当前应用每一个jar包里面 META-INF/services/javax.servlet.ServletContainerInitializer 指定的实现类(全限定路径名),启动并运行这个实现类的方法

在容器启动时支持使用 @HandlerType() 自动扫描感兴趣的类,并将加载其子类和实现类(不包括本身),存放到 Set> 集合中:

  1. @HandlesTypes(value = {感兴趣的类型})
  2. public class MyServletContainerInitializer implements ServletContainerInitializer {
  3. /**
  4. * @param c Set集合,即上述@HandlesTypes注解扫描进来的类集合
  5. * @param ctx servletContext,容器上下文
  6. * @throws ServletException
  7. */
  8. @Override
  9. public void onStartup(Set<Class<?>> c, ServletContext ctx) throws ServletException {
  10. }
  11. }

SpringServletContainerInitializer

SpringServletContainerInitializer:由 spring-web 提供,使用 servlet3.0 基于 spi 的插件能力,能够在容器启动时被 servlet 容器启动并加载
image.png
SpringServletContainerInitializer :在容器启动的时候加载 WebApplicationInitializer 接口的实现类并运行实现类中的 onStartup() 方法

  1. @HandlesTypes(WebApplicationInitializer.class)
  2. public class SpringServletContainerInitializer implements ServletContainerInitializer {
  3. // ....
  4. }

因此:

  • 在引入 spring-web 的情况下可以使用 WebApplicationInitializer 的实现类来加载相应的 servlet、filter 和 listener

WebApplicationInitializer 接口

官方文档:https://docs.spring.io/spring-framework/docs/current/reference/html/web.html#mvc-container-config

WebApplicationInitializer 接口在 spring-webmvc 包中做了相关抽象实现,用来加载 Spring 容器:

  • AbstractContextLoaderInitializer:用来创建根容器,createRootApplicationContext()
  • AbstractDispatcherServletInitializer:
    • 创建一个 web 的 ioc 容器:createServletApplicationContext()
    • 创建 dispatcherServlet:createDispatcherServlet()
    • 将创建的 DispatcherServlet 添加到 ServletContext 中:getServletMappings()
  • AbstractAnnotationConfigDispatcherServletInitializer:注解方式配置的 DispatcherServlet 初始化器
    • 创建根容器:createRootApplicationContext()
    • 传入一个配置类:getRootConfigClasses()
    • 创建 web 的 ioc 容器:createServletApplicationContext()
    • 获取配置类:getServletConfigClasses()

简单来说,以注解方式来启动 SpringMVC,只需要继承 AbstractAnnotationConfigDispatcherServletInitializer 抽象类,实现抽象方法指定 DispatcherServlet 的配置信息:

  1. public class WebInitializer extends AbstractAnnotationConfigDispatcherServletInitializer {
  2. @Override
  3. protected Class<?>[] getRootConfigClasses() {
  4. // 创建 Spring 父容器配置
  5. return new Class[]{ApplicationConfig.class};
  6. }
  7. @Override
  8. protected Class<?>[] getServletConfigClasses() {
  9. // 创建 SpringMVC 容器配置
  10. return new Class[]{WebConfig.class};
  11. }
  12. @Override
  13. protected String[] getServletMappings() {
  14. // DispatcherServlet 的映射路径
  15. return new String[]{"/"};
  16. }
  17. }