Anyone who has worked on Spring would have definitely used Spring Web MVC. That is how I also started with Spring. Spring Web MVC is a core part of the Spring Framework and its main purpose is to simplify the development of web applications. It provides a lot of features to build robust and flexible web applications. In this blog, we will cover the basics of Spring Web MVC and some of the most commonly used annotations and features. Knowing these features will help you build web applications and APIs more efficiently.
Spring Web uses the Model-View-Controller (MVC) design pattern to separate the concerns of an application.
Spring MVC uses Servlets under the hood to handle HTTP requests and responses. The DispatcherServlet
is the front controller that receives all incoming requests and dispatches them to the appropriate controllers based on the request mappings.
Spring Web uses Tomcat as the default embedded server, but you can use other servers like Jetty or Undertow as well.
@Controller public class HomeController { @GetMapping("/") public String home() { return "home"; // Returns the view name "home" } }
@Controller
and @ResponseBody
. Suitable for RESTful APIs which typically returns JSON data. Returned objects are automatically serialized to JSON.record Customer(Long id, String name) {} @RestController public class CustomerController { @GetMapping("/customers") public List<Customer> getCustomer() { return List.of(new Customer(1L, "Alice"), new Customer(2L, "Bob")); } }
@RequestMapping("/users") @RestController public class UserController { @GetMapping public List<String> getUsers() { return List.of("User1", "User2"); } }
@GetMapping("/users/{id}") public String getUser(@PathVariable String id) { return "User ID: " + id; } @PostMapping("/users") public String createUser(@RequestBody User user) { return "Created user: " + user.getName(); }
@GetMapping("/search") public String search(@RequestParam String query) { return "Searching for: " + query; }
@GetMapping("/users/{id}") public String getUserById(@PathVariable("id") String userId) { return "User ID: " + userId; }
@GetMapping("/request-attribute") public String getRequestAttribute(@RequestAttribute("attribute1") String attribute1) { return "Attribute1: " + attribute1; }
@Controller @SessionAttributes("user") public class UserController { @ModelAttribute("user") public User getUser() { return new User("Default Name"); } }
@PostMapping("/users") public String createUser(@RequestBody User user) { return "User created: " + user.getName(); }
@RestController
.@ResponseBody @GetMapping("/message") public String getMessage() { return "Hello, World!"; }
@GetMapping("/header") public String getHeader(@RequestHeader("User-Agent") String userAgent) { return "User-Agent: " + userAgent; }
@GetMapping("/cookie") public String getCookie(@CookieValue("sessionId") String sessionId) { return "Session ID: " + sessionId; }
@ControllerAdvice public class GlobalExceptionHandler { // Handles UserNotFoundException @ExceptionHandler(UserNotFoundException.class) public ResponseEntity<String> handleUserNotFoundException(UserNotFoundException ex) { return new ResponseEntity<>("User not found", HttpStatus.NOT_FOUND); } // Handles all other exceptions @ExceptionHandler(Exception.class) public ResponseEntity<String> handleException(Exception ex) { return new ResponseEntity<>("Error: " + ex.getMessage(), HttpStatus.INTERNAL_SERVER_ERROR); } }
@ModelAttribute("user") public User getUser() { return new User("Default Name"); } @GetMapping("/form") public String showForm() { return "formView"; }
@GetMapping("/greeting") public String greeting(Model model) { model.addAttribute("message", "Hello, World!"); return "greetingView"; }
@GetMapping("/response") public ResponseEntity<String> getResponse() { return ResponseEntity.ok("Success response"); }
ResponseEntity
allows you to set the status code, headers, and body of the response. In the example above, we are returning a 200 OK response with the body "Success response".
Say if you want to return a 404 Not Found response, you can do it like this:
@GetMapping("/not-found") public ResponseEntity<String> notFound() { return ResponseEntity.notFound().build(); }
@PostMapping("/upload") public String uploadFile(@RequestParam("file") MultipartFile file) { // Save the file return "Uploaded file: " + file.getOriginalFilename(); }
@GetMapping("/download/{fileName}") public ResponseEntity<Resource> downloadFile(@PathVariable String fileName) { Path file = Paths.get("uploads/" + fileName); Resource resource = new UrlResource(file.toUri()); return ResponseEntity.ok() .header(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename=\"" + resource.getFilename() + "\"") .body(resource); }
@CrossOrigin(origins = "http://example.com") @GetMapping("/cors") public String corsEnabledEndpoint() { return "CORS enabled"; }
record User(@NotBlank(message = "Name is required") String name) {} @PostMapping("/users") public String createUser(@Valid @RequestBody User user) { return "User created: " + user.getName(); }
If name is not provided in the request body, a MethodArgumentNotValidException
will be thrown with the message "Name is required". This can be handled using @ExceptionHandler
.
This cheat sheet provides an overview of key annotations and concepts in Spring Web. Did I miss something? Let me know in the comments in Medium or LinkedIn. Happy coding!
follow us on YouTube, LinkedIn, and Medium.
Check out this where I am applying most of these concepts in a real-world project:
This guide explores the features and usage of the RestClient introduced in Spring 6, providing a modern and fluent API for making HTTP requests. It demonstrates how to create and customize RestClient instances, make API calls, and handle responses effectively.
Learn how to create efficient integration tests for your Spring Boot APIs using Testcontainers and the Rest Assured library. This blog will guide you through building fluent integration tests for an API that interacts with MongoDB and AWS S3.
Get instant AI-powered summaries of YouTube videos and websites. Save time while enhancing your learning experience.