DispatcherServlet
Spring MVC与其他许多Web框架一样,是基于前端控制器(front controller)模式设计的。在这个模式中,一个中央的Servlet——即DispatcherServlet——提供了请求处理的共享算法,而实际的工作则由可配置的委托组件(delegate components)来完成。这种模型具有灵活性,能够支持多种工作流程。
DispatcherServlet与任何Servlet一样,需要根据Servlet规范通过Java配置或在web.xml中进行声明和映射。反过来,DispatcherServlet利用Spring配置来发现其进行请求映射、视图解析、异常处理等所需的委托组件(详见[special-bean-types.md])。
以下是Java配置的示例,该配置注册并初始化了DispatcherServlet,该Servlet由Servlet容器自动检测(参见Servlet Config):
- Java
- Kotlin
public class MyWebApplicationInitializer implements WebApplicationInitializer {
@Override
public void onStartup(ServletContext servletContext) {
// Load Spring web application configuration
AnnotationConfigWebApplicationContext context = new AnnotationConfigWebApplicationContext();
context.register(AppConfig.class);
// Create and register the DispatcherServlet
DispatcherServlet servlet = new DispatcherServlet(context);
ServletRegistration.Dynamic registration = servletContext.addServlet("app", servlet);
registration.setLoadOnStartup(1);
registration.addMapping("/app/*");
}
}
class MyWebApplicationInitializer : WebApplicationInitializer {
override fun onStartup(servletContext: ServletContext) {
// Load Spring web application configuration
val context = AnnotationConfigWebApplicationContext()
context.register(AppConfig::class.java)
// Create and register the DispatcherServlet
val servlet = DispatcherServlet(context)
val registration = servletContext.addServlet("app", servlet)
registration.setLoadOnStartup(1)
registration.addMapping("/app/*")
}
}
除了直接使用 ServletContext API 之外,你还可以扩展 AbstractAnnotationConfigDispatcherServletInitializer 并重写特定方法(请参见 上下文层次结构 下的示例)。
对于程序化的使用场景,GenericWebApplicationContext可以作为AnnotationConfigWebApplicationContext的替代选项。详情请参见GenericWebApplicationContext的Javadoc。
以下是一个web.xml配置的示例,该示例用于注册和初始化DispatcherServlet:
<web-app>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/app-context.xml</param-value>
</context-param>
<servlet>
<servlet-name>app</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value></param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>app</servlet-name>
<url-pattern>/app/*</url-pattern>
</servlet-mapping>
</web-app>
Spring Boot遵循不同的初始化顺序。它不依赖于Servlet容器的生命周期,而是通过Spring配置来启动自身以及嵌入的Servlet容器。Filter和Servlet的声明会在Spring配置中被检测到,并注册到Servlet容器中。更多详情,请参阅Spring Boot文档。
部分总结
📄️ 上下文层次结构
DispatcherServlet 需要一个 WebApplicationContext(普通 ApplicationContext 的扩展)来配置自身。WebApplicationContext 与它所关联的 ServletContext 和 Servlet 有联系。它还与 ServletContext 相绑定,这样应用程序就可以使用 RequestContextUtils 的静态方法来查找 WebApplicationContext(如果需要访问它的话)。
📄️ 特殊豆类类型
在Reactive栈中可找到等效的实现。
📄️ Web MVC 配置
在Reactive栈中可找到等效的实现。
📄️ Servlet Config
在Servlet环境中,你可以选择以编程方式配置Servlet容器,或者将其与web.xml文件结合使用。以下示例注册了一个DispatcherServlet:
📄️ 处理;加工
在Reactive栈中可找到等效的实现。
📄️ 路径匹配
Servlet API 将完整的请求路径作为 requestURI 暴露出来,并进一步将其细分为 contextPath、servletPath 和 pathInfo,这些值会根据 Servlet 的映射方式而有所不同。基于这些输入,Spring MVC 需要确定用于映射处理器的查找路径,该路径应该排除 contextPath 以及任何适用的 servletMapping 前缀。
📄️ 拦截;截击;截断;截距
所有HandlerMapping实现都支持处理器拦截(handler interception),当您希望在多个请求中应用相同功能时,这一点非常有用。HandlerInterceptor可以实现以下功能:
📄️ 异常(Exceptions)
在Reactive堆栈中可找到等效的实现。
📄️ 视图分辨率
在Reactive栈中可看到等效的实现。
📄️ Locale
Spring架构的大部分部分都支持国际化,Spring Web MVC框架也是如此。DispatcherServlet允许你使用客户端的区域设置(locale)来自动解析消息。这是通过LocaleResolver对象来实现的。
📄️ Multipart Resolver
在Reactive框架中可找到等效的实现。
📄️ 日志记录
参见Reactive栈中的等效实现。