Spring MVC 和其他许多 Web 框架一样,是围绕前台控制器(front controller)模式设计的,其中一个 中央 Servlet,即 DispatcherServlet,为请求处理提供了一个共享算法,而实际工作则由可配置的委托组件执行。这种模式很灵活,支持不同的工作流程。

    DispatcherServlet 和其他 Servlet 一样,需要通过使用 Java 配置或在 web.xml 中根据 Servlet 规范进行声明和映射。反过来,DispatcherServlet 使用 Spring 配置来发现它在请求映射、视图解析、异常处理等方面需要的委托组件。

    下面这个 Java 配置(这种方式可以配合内嵌 tomcat 实现 SpringBoot 那种方式启动)的例子注册并初始化了 DispatcherServlet,它是由 Servlet 容器自动检测出来的(见 Servlet 配置):

    1. public class MyWebApplicationInitializer implements WebApplicationInitializer {
    2. @Override
    3. public void onStartup(ServletContext servletContext) {
    4. // 加载 Spring web application configuration
    5. AnnotationConfigWebApplicationContext context = new AnnotationConfigWebApplicationContext();
    6. context.register(AppConfig.class);
    7. // 创建和注册 DispatcherServlet
    8. DispatcherServlet servlet = new DispatcherServlet(context);
    9. ServletRegistration.Dynamic registration = servletContext.addServlet("app", servlet);
    10. registration.setLoadOnStartup(1);
    11. registration.addMapping("/app/*");
    12. }
    13. }

    :::info 除了直接使用 ServletContext API 外,你还可以扩展 AbstractAnnotationConfigDispatcherServletInitializer 并覆盖特定的方法(见 Context Hierarchy 下的例子)。 :::

    以下是 web.xml 配置的例子,它注册并初始化了 DispatcherServlet:

    1. <web-app>
    2. <listener>
    3. <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
    4. </listener>
    5. <context-param>
    6. <param-name>contextConfigLocation</param-name>
    7. <param-value>/WEB-INF/app-context.xml</param-value>
    8. </context-param>
    9. <servlet>
    10. <servlet-name>app</servlet-name>
    11. <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
    12. <init-param>
    13. <param-name>contextConfigLocation</param-name>
    14. <param-value></param-value>
    15. </init-param>
    16. <load-on-startup>1</load-on-startup>
    17. </servlet>
    18. <servlet-mapping>
    19. <servlet-name>app</servlet-name>
    20. <url-pattern>/app/*</url-pattern>
    21. </servlet-mapping>
    22. </web-app>

    :::info Spring Boot 遵循不同的初始化顺序。Spring Boot 不是挂入 Servlet 容器的生命周期,而是使用 Spring 配置来启动自己和嵌入式 Servlet 容器。过滤器和 Servlet 声明在 Spring 配置中被检测到,并在 Servlet 容器中注册。更多细节请参见 Spring Boot 文档。 :::