(我已经知道答案了,但是由于我经常发现自己在寻找答案,因此我将其发布为自己和其他人的文档。这是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映射。
此机制如何工作?
答案 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容器首先查找位于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确实包含一个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中找到。