框架(如Spring)如何在没有web.xml的情况下配置Servlet容器?

时间:2019-05-23 19:07:56

标签: java spring spring-boot spring-mvc servlets

(我已经知道答案了,但是由于我经常发现自己在寻找答案,因此我将其发布为自己和其他人的文档。这是Stackoverflow上的encouraged。)< / sub>

背景介绍

许多Servlet开发人员已阅读“ Head First Serlet&JSP”一书,以获取“认证的Web组件开发人员考试”或只是学习Servlet。但是该书自2009年以来就没有更新过,仅涉及Servlet 2.4。从那以后很多事情改变了。当前的最新版本是4.0。 改变的一件事是servlet Web应用程序的启动过程,这可能使启动过程中不清楚发生什么以及如何初始化Web应用程序。

问题

在Servlet 2.4及更低版本中,web.xml用于完全配置Web应用程序。但是更高的版本似乎还有其他配置Web应用程序的方式,而无需触摸web.xml和注释。例如,以.jar文件形式提供的Web框架能够以某种方式挂接到Servlet容器中并添加url映射。

此机制如何工作?

1 个答案:

答案 0 :(得分:2)

简介

在Servlet 2.4(2003年11月)中,一个 servlet容器(例如Tomcat和Jetty)只是通过查找文件WEB-INF/web.xml部署描述符< / em>)。文件web.xml包含对servlet,过滤器和侦听器的引用,以及它们的关联url模式和参数。 servlet容器使用web.xml确切地知道在哪里可以找到所有内容以及如何配置它们。

从Servlet 3.0(2009年12月)开始,web.xml是可选的,使用也可以使用批注或编程配置。

注释很简单,您可以分别使用@ javax.servlet.annotation。WebServlet,@ WebFilter和@ WebListener来注释servlet,过滤器或侦听器,这允许servlet容器查找和检测这些类。但是,注释的确提供了比web.xml和程序化配置少的配置功能。<​​/ p>

本文进一步着重于如何配置编程配置以及如何启动Spring MVC。它比注释要复杂一点,但是确实为您和框架设计人员提供了对启动过程的更多控制。

如果要在Servlet 3.0之前使用Web框架,则必须在Web.xml中添加一个Servlet或过滤器,然后从那里配置框架。初始化之后,您可以开始编写Web框架已知的类(通常是非Servlet类)来创建Web应用程序。

从Servlet 3.0开始,该系统是模块化的。这样,框架和库设计人员就可以初始化servlet容器,而无需通过web.xml配置框架。您可以立即开始编写特定于Web框架的类以创建Web应用程序,而无需接触Servlet类。 (在Servlet 3.0中也可以创建自己的web.xml,并且仍然允许框架对框架进行初始化,而无需在web.xml中进行定义。)

框架或库如何自动挂接到Servlet容器中?

启动时,Servlet容器首先查找位于WEB-INF/web.xml的部署描述符。如果此文件的metadata-complete属性设置为false,或者根本没有定义,则容器还将搜索带注释的类,例如@WebServlet。

除了查找web.xml和带注释的类之外,从Servlet 3.0开始,容器还将在META-INF/web-fragment.xml目录中的.jar文件中查找WEB-INF/lib文件。

文件web-fragment.xml是网络片段,即:

  

Web应用程序的逻辑分区,其方式为   Web应用程序中使用的框架可以定义所有   工件,而无需开发人员在其中编辑或添加信息   web.xml。它几乎可以包含与web.xml相同的所有元素   描述符用途。但是,描述符的顶级元素必须   是网络片段,必须调用相应的描述符文件   web-fragment.xml。排序相关元素之间也有所不同   web-fragment.xml和web.xml

web-fragment.xml的内容类似于web.xml,但具有一个web-fragment根元素而不是web-app元素:

<web-fragment xmlns="http://java.sun.com/xml/ns/javaee"
              xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
              xsi:schemaLocation="http://java.sun.com/xml/ns/javaee 
              https://java.sun.com/xml/ns/javaee/web-fragment_3_0.xsd"
              version="3.0">
  <filter>
    <filter-name>FrameworkFilter</filter-name>
    <filter-class>framework.FrameworkFilter</filter-class>
  </filter>

  <filter-mapping>
    <filter-name>FrameworkFilter</filter-name>
    <url-pattern>/*</url-pattern>
  </filter-mapping>
</web-fragment>

可以使用<absolute-ordering><ordering>来配置单个web.xml和多个web-fragment.xml文件的确切加载顺序。

除Web片段外,还有一种编程方法可对Web应用程序进行分区:通过编写接口javax.servlet.ServletContainerInitializer的实现。 ServletContainerInitializer允许访问ServletContext,其中包含用于以编程方式添加servlet,过滤器和侦听器的方法。 要使用ServletContainerInitializer,必须在META-INF/services/javax.servlet.ServletContainerInitializer中的文件中指定它。该文件的内容必须是实现类的完全限定路径。

这对Spring MVC如何起作用?

尽管Spring MVC确实包含一个web-fragment.xml,但它没有定义任何servlet,过滤器或监听器。 Spring使用javax.servlet.ServletContainerInitializer文件初始化ServletContainerInitializer类实例。该文件包含对类SpringServletContainerInitializer的引用。

SpringServletContainerInitializer是ServletContainerInitializer,因此在启动时会收到ServletContext。 SpringServletContainerInitializer的目标是将ServletContext传递给对开发人员更友好的WebApplicationInitializer,以便您可以添加Servlet,例如Springs DispatcherServlet,它是将传入请求定向到其他控制器的前端控制器。 (有关如何将DispatcherServlet配置为Spring的信息,请参见spring-framework-reference。)

Spring MVC没有提供WebApplicationInitializer的具体实现,仅提供了许多抽象类,因此您可以控制启动过程。对于Spring Boot,提供了一个具体的实现:SpringApplicationWebApplicationInitializer,以减少样板代码的数量。

其他信息

有关Servlet容器启动过程的确切工作方式的详细说明,可以在官方Java Servlet Specification中找到。