Spring MVC

Last update: 2023-11-03 17:36:24 +0800 +0800
Available translations: 日本語 / 中文(简体) / 中文(繁體)

Spring MVC is the Servlet-based web framework in Spring Framework. Its front controller, DispatcherServlet, coordinates request mapping, argument resolution, controller invocation, return-value handling, and exception translation. Spring WebFlux uses a different reactive runtime and threading model; the two frameworks must not be treated as interchangeable.

Bootstrap and Dispatch #

A non-Boot Servlet application can register a web application context and dispatcher through WebApplicationInitializer:

java
public final class WebInitializer implements WebApplicationInitializer {
    @Override
    public void onStartup(ServletContext servletContext) {
        var context = new AnnotationConfigWebApplicationContext();
        context.register(WebConfiguration.class);

        var servlet = servletContext.addServlet(
            "mvc", new DispatcherServlet(context));
        servlet.setLoadOnStartup(1);
        servlet.addMapping("/");
    }
}

Spring Boot performs equivalent registration for an MVC application. Mapping the dispatcher to / lets the Servlet container retain special handling for static resources and JSPs; /* also captures those dispatches.

For each request, the dispatcher:

  1. asks ordered HandlerMapping implementations for a handler and interceptors;
  2. selects a HandlerAdapter capable of invoking that handler;
  3. invokes pre-handle interceptors and the handler;
  4. processes the return value as a response body, view, async result, or another supported form; and
  5. runs exception resolvers and completion interceptors.

MVC strategy objects are beans in the dispatcher context. @EnableWebMvc imports the standard configuration for a plain Spring application. In Spring Boot, implement WebMvcConfigurer to extend Boot’s configuration instead of adding @EnableWebMvc, which takes full control from auto-configuration.

Request Mapping, Binding, and Validation #

Annotated controllers map by path, HTTP method, parameters, headers, consumed media types, and produced media types:

java
@PostMapping(
    path = "/orders",
    consumes = MediaType.APPLICATION_JSON_VALUE,
    produces = MediaType.APPLICATION_JSON_VALUE)
ResponseEntity<OrderView> create(@Valid @RequestBody CreateOrder request) {
    return ResponseEntity.status(HttpStatus.CREATED)
        .body(orderService.create(request));
}

HandlerMethodArgumentResolver implementations supply path variables, query parameters, headers, cookies, principals, Servlet objects, model attributes, and request bodies. Simple textual values use conversion and formatting. @ModelAttribute binds named properties through WebDataBinder; define allowed fields or use a dedicated command type because binding is an input security boundary. @RequestBody instead delegates media decoding to an HttpMessageConverter.

@Valid applies Jakarta Bean Validation, while @Validated can also select validation groups. For model-attribute binding, a BindingResult parameter immediately following the bound argument lets the controller inspect conversion and validation errors. Without local handling, MVC translates validation exceptions through its exception-resolution chain.

Return Values and Content Negotiation #

HandlerMethodReturnValueHandler implementations process values such as ModelAndView, view names, ResponseEntity, ProblemDetail, and objects annotated with @ResponseBody. Response-body values are encoded by an HttpMessageConverter.

Content negotiation compares the handler’s produces conditions, the request’s acceptable media types, and converter capabilities. A request body with an unsupported Content-Type produces 415; no acceptable response representation produces 406. Prefer the Accept header and explicit defaults over path-extension negotiation.

Exception Resolution #

HandlerExceptionResolver turns failures into a model, status, or response. The standard annotated configuration includes:

  • ExceptionHandlerExceptionResolver for controller and @ControllerAdvice exception methods;
  • ResponseStatusExceptionResolver for @ResponseStatus and ResponseStatusException; and
  • DefaultHandlerExceptionResolver for framework exceptions.

Central advice should map domain failures to stable status codes and a consistent error schema. Spring Framework 6 introduced ProblemDetail and ErrorResponse; Spring 6.1 documentation describes their problem-details support in terms of RFC 9457, which superseded RFC 7807.

Threads, Async Requests, and Context #

Synchronous MVC handling runs on a Servlet-container thread. Blocking database or HTTP calls retain that thread until completion, so configure deadlines and capacity from the connector through every downstream dependency.

A controller can return Callable, DeferredResult, or WebAsyncTask. MVC starts Servlet asynchronous processing, releases the container thread, and performs a later ASYNC dispatch when the result is ready. Async MVC does not make blocking code non-blocking; it moves work to another executor. Configure that executor, timeouts, cancellation, and overload behavior explicitly.

Thread-local logging, locale, security, and observation state do not automatically follow arbitrary executor tasks. Use supported interceptors or task decorators, or pass context explicitly, and always clear restored state.

Primary References #

Comments

Read or comment on GitHub (sign-in required to comment)