How does Spring Boot register and configure the DispatcherServlet? Walk through DispatcherServletAutoConfiguration.
answer
- No web.xml — programmatic registration
- servlet bean + DispatcherServletRegistrationBean
- mapped to spring.mvc.servlet.path (default '/')
- single Boot context, no root/child split
- @ConditionalOnMissingBean = override-able
basics
~10 sSpring Boot's DispatcherServletAutoConfiguration creates the DispatcherServlet bean and a DispatcherServletRegistrationBean that registers it with the embedded servlet container, mapped to spring.mvc.servlet.path (default '/'), using the single Boot application context.
solid answer
~40 sIn Spring Boot there's no web.xml. `DispatcherServletAutoConfiguration` (in `spring-boot-autoconfigure`, gated on a servlet web app with `DispatcherServlet` on the classpath) provides two nested configs: `DispatcherServletConfiguration` creates the `DispatcherServlet` bean (named `dispatcherServlet`), binding `spring.mvc` / `server` properties like `throwExceptionIfNoHandlerFound`; and `DispatcherServletRegistrationConfiguration` creates a `DispatcherServletRegistrationBean` that registers the servlet with the embedded container (Tomcat/Jetty/Undertow) and maps it to `spring.mvc.servlet.path` (default `'/'`). Because Boot uses a **single** application context, the DispatcherServlet uses that context directly rather than creating a child — the classic root/servlet split is gone. Registration goes through Boot's `ServletContextInitializer`/`RegistrationBean` mechanism against the programmatic `ServletContext`, not `ServletConfig` XML. `@ConditionalOnMissingBean` lets you override either bean. Multipart is wired by a separate autoconfiguration.
code
java · 40 lines// Shape of Spring Boot's auto-config (abridged, illustrative)
@AutoConfiguration(after = ServletWebServerFactoryAutoConfiguration.class)
@ConditionalOnWebApplication(type = Type.SERVLET)
@ConditionalOnClass(DispatcherServlet.class)
public class DispatcherServletAutoConfiguration {
@Configuration(proxyBeanMethods = false)
@ConditionalOnClass(ServletRegistration.class)
protected static class DispatcherServletConfiguration {
@Bean(name = "dispatcherServlet")
@ConditionalOnMissingBean
public DispatcherServlet dispatcherServlet(WebMvcProperties props) {
DispatcherServlet d = new DispatcherServlet();
d.setThrowExceptionIfNoHandlerFound(props.isThrowExceptionIfNoHandlerFound());
d.setDispatchOptionsRequest(props.isDispatchOptionsRequest());
return d;
}
}
@Configuration(proxyBeanMethods = false)
protected static class DispatcherServletRegistrationConfiguration {
@Bean(name = "dispatcherServletRegistration")
@ConditionalOnMissingBean(value = DispatcherServlet.class,
name = "dispatcherServletRegistration")
public DispatcherServletRegistrationBean dispatcherServletRegistration(
DispatcherServlet dispatcherServlet, WebMvcProperties props) {
return new DispatcherServletRegistrationBean(
dispatcherServlet, props.getServlet().getPath()); // default "/"
}
}
}
// Add a SECOND dispatcher for, say, an isolated API:
@Bean
public ServletRegistrationBean<DispatcherServlet> apiDispatcher(DispatcherServlet ds) {
ServletRegistrationBean<DispatcherServlet> reg =
new ServletRegistrationBean<>(ds, "/api2/*");
reg.setName("apiDispatcher");
return reg;
}go deeper
Know Boot auto-registers the DispatcherServlet mapped to '/'.
Know the servlet bean + registration bean and the spring.mvc.servlet.path property.
Explain programmatic RegistrationBean registration and @ConditionalOnMissingBean override points.
Discuss the single-context consequence, multiple-dispatcher setups, ordering, and no-handler/error-path implications.
## The problem Boot solves Classic MVC registers the DispatcherServlet in `web.xml` or a `WebApplicationInitializer`, and builds a root+servlet context hierarchy. Spring Boot runs an **embedded** servlet container and has no `web.xml`, so it must register the DispatcherServlet **programmatically** and configure it from properties. ## DispatcherServletAutoConfiguration Lives in `org.springframework.boot.autoconfigure.web.servlet`. Key conditions/ordering: - `@AutoConfiguration(after = ServletWebServerFactoryAutoConfiguration.class)` — the web server factory must be configured first. - `@ConditionalOnWebApplication(type = SERVLET)` and `@ConditionalOnClass(DispatcherServlet.class)`. It declares two nested `@Configuration` classes: ### 1. DispatcherServletConfiguration — the servlet bean - `@Bean(name = DEFAULT_DISPATCHER_SERVLET_BEAN_NAME)` → `dispatcherServlet` creates a `DispatcherServlet`. - It copies bound properties: from `WebMvcProperties` it sets things like `setDispatchOptionsRequest`, `setDispatchTraceRequest`, `setThrowExceptionIfNoHandlerFound`, `setPublishEvents`, `setEnableLoggingRequestDetails`. - Guarded by `@ConditionalOnMissingBean` (matched by the well-known name) so you can define your own. - Also conditionally exposes a `MultipartResolver` bean renaming fix (`multipartResolver`) if a bean of another name exists. ### 2. DispatcherServletRegistrationConfiguration — the registration - `@Bean` → `DispatcherServletRegistrationBean` (a `ServletRegistrationBean` subclass). - It maps the servlet to `webMvcProperties.getServlet().getPath()` — property `spring.mvc.servlet.path`, default `'/'`. - `@ConditionalOnMissingBean(value = DispatcherServlet.class, name = DEFAULT_DISPATCHER_SERVLET_REGISTRATION_BEAN_NAME)` — override-able. - The registration bean implements `ServletContextInitializer`; at container startup Boot calls `onStartup(ServletContext)` which does `servletContext.addServlet(...).addMapping(...)`. This is the programmatic equivalent of the old `web.xml` `<servlet-mapping>`. ## Single context, no hierarchy Crucially, the Boot-created DispatcherServlet is given the **existing** application context (Boot sets it, and `FrameworkServlet` won't create a child because a context is already supplied). So there's **one** context — root and servlet beans coexist. This is why Boot apps don't hit the classic duplicate-scan / cross-context AOP problems. ## ServletConfig vs. programmatic registration In a servlet container, a servlet receives a `ServletConfig` (init params, servlet name, ServletContext). In XML you'd set `contextConfigLocation` init-params. In Boot, the `RegistrationBean` supplies init params programmatically via `setInitParameters(...)`, and the servlet name/mapping via the registration bean. You rarely touch `ServletConfig` directly. ## Customization hooks - Change the mapping/path: `spring.mvc.servlet.path=/app` (note: this becomes a servlet path prefix, affects `@RequestMapping` base and `ServletContext` path handling). - `spring.mvc.throw-exception-if-no-handler-found`, `spring.mvc.dispatch-options-request`, etc. - Register a **second** DispatcherServlet by defining your own `ServletRegistrationBean<DispatcherServlet>` with a distinct mapping (e.g. a separate API context). - Override the servlet entirely with your own `@Bean DispatcherServlet` (thanks to `@ConditionalOnMissingBean`). ## Gotchas - Setting `spring.mvc.servlet.path` to something other than `/` changes how static resources and the error path resolve; the default `/` maps everything. - The registration bean's **order** matters if you register multiple servlets/filters. - `throwExceptionIfNoHandlerFound` behavior: in recent Boot versions no-handler results in a `NoHandlerFoundException` funneled to the error handling, but historically returning a container 404 that bypassed `@ControllerAdvice` was a common surprise. - Because there's a single context, an errant `@ComponentScan` can no longer 'hide' web beans from services — but it also means everything shares one lifecycle.
- Why does a Spring Boot app not suffer the classic duplicate-component-scan problem?Because Boot uses a single application context and hands it to the DispatcherServlet instead of creating a child servlet context — there's no second context to re-scan into.
- How would you change the DispatcherServlet's URL mapping in Boot?Set spring.mvc.servlet.path (default '/'). It's consumed by DispatcherServletRegistrationBean to set the servlet mapping; be aware it also shifts static-resource and error path resolution.
- How can you fully replace Boot's DispatcherServlet?Define your own @Bean named dispatcherServlet (and/or the registration bean). Both are guarded by @ConditionalOnMissingBean, so your bean wins and auto-config backs off.
- What replaces web.xml servlet registration in Boot?The ServletContextInitializer / RegistrationBean mechanism: DispatcherServletRegistrationBean.onStartup calls servletContext.addServlet(...).addMapping(...) programmatically at embedded-container startup.
saying these in an interview costs you the question
- Saying Boot uses web.xml to register the DispatcherServlet
- Claiming Boot still builds a separate root and servlet context by default
- Thinking you can't override the DispatcherServlet bean
- Confusing spring.mvc.servlet.path with server.servlet.context-path