Spring MVC in Java
Introduction
Spring MVC (Model-View-Controller) is the cornerstone of web development in the Spring ecosystem. It is a robust web framework built on the Servlet API that provides a structured way to handle HTTP requests, separate concerns, and build both traditional server-side rendered web applications and modern RESTful web services.
By cleanly separating the data (Model), the user interface (View), and the request processing logic (Controller), Spring MVC ensures that web applications are highly modular, testable, and maintainable.
Core Architecture and Lifecycle
At the heart of Spring MVC lies the Front Controller design pattern. The central component is the DispatcherServlet, which acts as the main gateway for all incoming HTTP requests.
Request Processing Workflow
- Incoming Request: The client sends an HTTP request to the web server, which is intercepted by the
DispatcherServlet. - Handler Mapping: The
DispatcherServletconsults theHandlerMappingto find the appropriate Controller method (Handler) mapped to the requested URL. - Execution: The Controller executes the business logic (often delegating to a Service layer) and populates a
Modelwith data. - View Resolution (Traditional MVC): The Controller returns a logical view name to the
DispatcherServlet. TheViewResolverresolves this string into an actual View (e.g., Thymeleaf, JSP). - Message Conversion (REST API): If the Controller is a
@RestController, the returned object is serialized directly into the HTTP response body (e.g., as JSON) usingHttpMessageConverters, bypassing View Resolution. - Response: The rendered view or serialized JSON is sent back to the client.
Code Examples
1. Traditional MVC Controller
In traditional web apps, the controller returns a view name and passes data via the Model.
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
@Controller
public class GreetingController {
@GetMapping("/greeting")
public String greeting(@RequestParam(name="name", required=false, defaultValue="World") String name, Model model) {
// Add data to the model
model.addAttribute("name", name);
// Return the logical view name (e.g., "greeting.html" if using Thymeleaf)
return "greeting";
}
}
2. RESTful Controller
For building APIs, @RestController combines @Controller and @ResponseBody, ensuring that the returned object is serialized into the HTTP response body.
import org.springframework.web.bind.annotation.*;
import org.springframework.http.ResponseEntity;
@RestController
@RequestMapping("/api/users")
public class UserController {
@GetMapping("/{id}")
public ResponseEntity<User> getUserById(@PathVariable Long id) {
User user = new User(id, "John Doe", "john.doe@example.com");
return ResponseEntity.ok(user);
}
@PostMapping
public ResponseEntity<User> createUser(@RequestBody User newUser) {
// In a real app, save to database via a Service
newUser.setId(System.currentTimeMillis());
return ResponseEntity.status(201).body(newUser);
}
}
Advanced Concepts
1. Global Exception Handling
Handling exceptions elegantly across all controllers is achieved using @ControllerAdvice.
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
@ControllerAdvice
public class GlobalExceptionHandler {
@ExceptionHandler(ResourceNotFoundException.class)
public ResponseEntity<String> handleNotFound(ResourceNotFoundException ex) {
return ResponseEntity.status(HttpStatus.NOT_FOUND).body(ex.getMessage());
}
}
2. Interceptors
Spring MVC Interceptors (HandlerInterceptor) allow you to pre-process and post-process HTTP requests before they reach the controller and before the response is sent back. They are ideal for logging, authentication checks, or modifying headers.
Summary
- Spring MVC is built on the Servlet API and uses the
DispatcherServletas a front controller. - It supports both traditional server-side rendering (
@Controller) and modern REST APIs (@RestController). - Key components include
HandlerMapping,ViewResolver, andHttpMessageConverter. - Advanced features like
@ControllerAdviceprovide clean, centralized exception handling.