Spring Web MVC is the original web framework built on the Servlet API and has been included in the Spring Framework from the very beginning.
Spring MVC 是基于Servlet API 的原生Web framework。之前对这个有误解,以为Spring MVC是另起炉灶的、新的web framework ,随着对Spring MVC的
了解才认识到这一点。
Spring MVC, as many other web frameworks, is designed around the front controller pattern where a central Servlet
, the DispatcherServlet
, provides a shared algorithm for request processing, while actual work is performed by configurable delegate components. This model is flexible and supports diverse workflows.
The DispatcherServlet
, as any Servlet
, needs to be declared and mapped according to the Servlet specification by using Java configuration or in web.xml
. In turn, the DispatcherServlet
uses Spring configuration to discover the delegate components it needs for request mapping, view resolution, exception handling, and more.
DispatcherServlet 使用Java configuration 或者
web.xml配置。
The following example of the Java configuration registers and initializes the DispatcherServlet
, which is auto-detected by the Servlet container (see Servlet Config):
使用Java configuration
时,实现WebApplicationInitializer 接口,不需要额外的配置,会自动被 Servlet 容器 (比如Tomcat) 发现。
1 public class MyWebApplicationInitializer implements WebApplicationInitializer { 2 3 @Override 4 public void onStartup(ServletContext servletCxt) { 5 6 // Load Spring web application configuration 7 AnnotationConfigWebApplicationContext ac = new AnnotationConfigWebApplicationContext(); 8 ac.register(AppConfig.class); 9 ac.refresh(); 10 11 // Create and register the DispatcherServlet 12 DispatcherServlet servlet = new DispatcherServlet(ac); 13 ServletRegistration.Dynamic registration = servletCxt.addServlet("app", servlet); 14 registration.setLoadOnStartup(1); 15 registration.addMapping("/app/*"); 16 } 17 }
In addition to using the ServletContext API directly, you can also extend AbstractAnnotationConfigDispatcherServletInitializer
and override specific methods (see the example under Context Hierarchy).
<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 follows a different initialization sequence. Rather than hooking into the lifecycle of the Servlet container, Spring Boot uses Spring configuration to bootstrap itself and the embedded Servlet container. Filter
and Servlet
declarations are detected in Spring configuration and registered with the Servlet container. For more details, see the Spring Boot documentation.
Context Hierarchy
DispatcherServlet
expects a WebApplicationContext
(an extension of a plain ApplicationContext
) for its own configuration. WebApplicationContext
has a link to the ServletContext
and the Servlet
with which it is associated. It is also bound to the ServletContext
such that applications can use static methods on RequestContextUtils
to look up the WebApplicationContext
if they need access to it.
(WebApplicationContext
和 ServletContext
"绑定",可以通过 RequestContextUtils 获得
WebApplicationContext。
For many applications, having a single WebApplicationContext
is simple and suffices. It is also possible to have a context hierarchy where one root WebApplicationContext
is shared across multiple DispatcherServlet
(or other Servlet
) instances, each with its own child WebApplicationContext
configuration. See Additional Capabilities of the ApplicationContext
for more on the context hierarchy feature.
The root WebApplicationContext
typically contains infrastructure beans, such as data repositories and business services that need to be shared across multiple Servlet
instances. Those beans are effectively inherited and can be overridden (that is, re-declared) in the Servlet-specific child WebApplicationContext
, which typically contains beans local to the given Servlet
. The following image shows this relationship:
1 public class MyWebAppInitializer extends AbstractAnnotationConfigDispatcherServletInitializer { 2 3 @Override 4 protected Class<?>[] getRootConfigClasses() { 5 return new Class<?>[] { RootConfig.class }; 6 } 7 8 @Override 9 protected Class<?>[] getServletConfigClasses() { 10 return new Class<?>[] { App1Config.class }; 11 } 12 13 @Override 14 protected String[] getServletMappings() { 15 return new String[] { "/app1/*" }; 16 } 17 }
1.1.2. Special Bean Types
The DispatcherServlet
delegates to special beans to process requests and render the appropriate responses. By “special beans” we mean Spring-managed Object
instances that implement framework contracts. Those usually come with built-in contracts, but you can customize their properties and extend or replace them.