• Spring注解驱动之ServletContainerInitializer使用


    概述

    上一节,我们说了Servlet3.0规范里面的一些简单注解,利用它们可以来注册Servlet、Filter及Listenser等组件。
    这一讲,我们来说ServletContainerInitializer。
    打开Servlet3.0标准规范文档,找到Annotations and pluggability这一章节下的8.2 Pluggability这一小节,找到之后,再找到该小节下的最后一个小节,即Shared libraries / runtimes pluggability,翻译过来,应该是共享库/运行时可插拔。
    在这里插入图片描述
    这是一个非常重要的机制,该机制在后来我们框架整合里面用到的非常多。

    Shared librarier/runtimes pluggability

    An instance of the ServletContainerInitializer is looked up via the jar services API by the container at container / application startup time.
    在容器(即Servlet容器,比如Tomcat)/应用程序启动时,容器通过jar服务API查找ServletContainerInitializer的实例。
    也就是当Servlet容器启动我们的应用时,它会扫描应用下每个jar包里面的ServeletContainerInitializer的实现类。那从哪里找呢,看文档上描述是必须把ServletContainerInitializer的实现类绑定在META-INF/services/ 目录下面名字叫javax.servlet.ServletContainerInitializer的文件里面。
    其实就是在META-INF/services/javax.servlet.ServletContainerInitializer文件里面写上ServletContainerInitializer实现类的全类名。
    总结一下:Servlet容器在启动应用的时候,扫描当前应用每个jar包里面的META-INF/services/javax.servlet.ServletContainerInitializer文件中指定的实现类,然后运行实现类。

    测试ServletContainerInitializer初始化机制

    参考https://blog.csdn.net/m0_51545690/article/details/123077550
    搭建一个普通的java项目,之前的maven项目演示有些问题,所以需要搭建一个简单的java项目,然后把项目部署到tomcat上。
    搭建完如下:
    在这里插入图片描述

    @HandlesTypes(HelloService.class)
    public class MyServletContainerInitializer implements ServletContainerInitializer {
        @Override
        public void onStartup(Set<Class<?>> set, ServletContext servletContext) throws ServletException {
            System.out.println("MyServletContainerInitializer.onStartup ...");
            System.out.println("class set:" + set);
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    我们根据文档描述指定,tomcat容器启动会调用MyServletContainerInitializer的onStartup的方法。
    该方法的两个参数是什么意思呢?

    • servletContext:它是来代表当前web应用的,一个web应用就对应这一个ServletContext对象。此外,它也是我们常说的四大域对象之一,我们给它里面存个东西,只要应用在不关闭之前,我们都可以在任何位置获取到。
    • Set>:我们可以参考Servlet 3.0规范的描述,在ServletContainerInitializer的实现类上使用一个@HandlesTypes注解,可以把指定类的子类传递过来。
      这里我们写一个接口和一个实现类。
    public interface HelloService {
    }
    public class HelloServiceImp implements HelloService{
    }
    
    • 1
    • 2
    • 3
    • 4

    在@HandlesType指定HelloService.class,就能把HelloServiceImp传递给我们。

    测试结果

    MyServletContainerInitializer.onStartup ...
    class set:[class com.study.servlet.HelloServiceImp]
    
    • 1
    • 2

    小结

    即Servlet容器在启动应用的时候,会将@HandlesTypes注解里面指定的类型下面的子类,包括实现类或者子接口等,全部都给我们传递过来。只要给我们传入了某一感兴趣的类型,就可以利用反射来创建对象了啊!

    总结

    以上就是基于运行时插件的ServletContainerInitializer机制。
    这个机制最重要的就是要启动ServletContainerInitializer的实现类,然后就能传入我们感兴趣的类型了。
    该机制有两个核心,一个是ServletContainerInitializer,一个是@HandlesTypes注解。

    参考

    Spring注解驱动开发第51讲——ServletContainerInitializer来了,傻孩子们,快跑啊!

  • 相关阅读:
    杭电oj 2048 神、上帝以及老天爷 C语言
    uniapp h5实现微信公众号登录
    如何处理使用MindSpore Lite的converter_lite工具转换模型失败的问题
    拉索回归(Lasso)算法原理讲解
    2022年上半年信息系统项目管理师下午案例分析真题及答案解析
    手把手带你用香橙派AIpro开发AI推理应用
    uni-app总结
    电力4G变倍云台摄像头低功耗测试对比
    始祖双碳新闻 | 2022年7月25日-7月31日碳中和行业早知道
    python_函数
  • 原文地址:https://blog.csdn.net/tianzhonghaoqing/article/details/126941656