SpringMVC的web配置——JDK中SPI机制的应用

  本文与其说是总结MVC的web配置,不如更精准的描述是web配置是约定的某一个标准的应用。这个标准本质是Servlet3.0以上标准的一个小知识点。

  一般入门的web项目,使用集成开发工具都会自建一个web.xml的文件。该文件中配置servlet/filter/listener等相关信息。如下图:

                

   Spring提供接口WebApplicationInitializer,通过自定义实现该接口配置web.xml里的相关信息。查看该接口源码:

                

   同时该接口源码注释中提供了多个示例,下图是示例之一:

                

  ,这个servletContext可以直接理解为常用的容器tomcat的一个实例。如果使用其他的符合servlet标准的容器,也可以理解为其他容器的一个实例。

  为什么单拧这个出来呢?这就涉及一个标准~Servlet3.0以上版本的标准吧。实际上Servlet3.0以上的标准为运行时可插拔,为SpringBoot自动配置MVC后并自动在容器中运行提供了可能。具体实现通过ServletContainerInitializer操作

    1)ServletContainerInitializer类通过jar services API查找。容器启动时,会创建一个ServletContainerInitializer实例。

    2)自定义的应用提供的ServletContainerInitializer实现类必须绑定在jar包的META-INF/services目录中的一个叫做javax.servlet.ServletContainerInitializer的文件中,并根据这个文件指定ServletContainerInitializer的实现。这个规则其实就是SPI机制的约定之一(参考Dubbo SPI机制之一JDK中的SPI)。

    3)除了ServletContainerInitializer外,还提供一个注解@HandlesTypes。在ServletContainerInitializer实现上的HandlesTypes注解用于表示感兴趣的一些类,他们可以指定@HandlesTypes的value中的注解(类型、方法或自动级别的),或者是其类型的超类继承/实现之一。

    当应用正在启动时,ServletContainerInitializer的OnStartup方法将被调用。ServletContainerInitializer's的OnStartup得到一个类的Set,其或者继承/实现initializer表示感兴趣的类,或者它是使用指定在@HandlesTypes注解中的任意类注解的。

  以上通过具体操作的解释如下:

  1、编写自定义一个类实现ServletContainerInitializer

                

    其方法名就是onStartup,调用自定义实现WebApplicationInitializer的类或子类的方法onStartup。

   2、通过@HandlesTypes传递web配置信息,编写实现WebApplicationInitializer的类即可。(可以是其他类或子类,但是此处是针对SpringMVC,必须实现WebApplicationInitializer)

                

    即onStartup中参数Set是实现WebApplicationInitializer接口的一些列类。

    具体的一个实现如下:

                

   3、文件编写META-INF/services目录中的一个叫做javax.servlet.ServletContainerInitializer

                

     文件内容为实现ServletContainerInitializer的类全限定名。

  启动tomcat容器时,tomcat自动扫描该项目jar下的所有META-INF/services目录中的一个叫做javax.servlet.ServletContainerInitializer的文件,执行文件MySpringServletContainerInitializer类的onStartup方法,并通过反射自动调用MyWebApplicationInitializer的onStartup方法。

  javax.servlet.ServletContainerInitializer作为纽带将容器与WebApplicationInitializer关联起来。下面验证SpringBoot中SpringMVC自动配置是否符合此逻辑:

    1、SpringBoot添加web依赖

                

     2、查看加载的jar中是否存在META-INF/services目录中的一个叫做javax.servlet.ServletContainerInitializer

                

    3、查看SpringServletContainerInitializer类具体实现

               

     4、查看WebApplicationInitializer的实现                   

posted on 2021-06-10 16:02  池塘里洗澡的鸭子  阅读(333)  评论(0编辑  收藏  举报