1. Introduction
In modern web development, Spring Boot has become a go-to framework for building robust and scalable RESTful APIs. One of the main reasons for its popularity lies in its annotation-driven programming model, which greatly simplifies the process of mapping web requests to backend logic.
In this article, we will explore how Web and REST annotations such as @RequestMapping, @GetMapping, @PostMapping, @PathVariable, @RequestParam, @RequestBody, and @ResponseBody are used to create a fully functional REST API in Spring Boot.
2. Problem
When building APIs, developers often face repetitive and verbose configurations to map HTTP requests (like GET, POST, PUT, DELETE) to Java methods. Before Spring Boot’s annotation-based approach, developers had to manually configure these routes and parse request parameters, making the code harder to maintain and understand.
- The controller code becomes cluttered with boilerplate.
- It’s harder to distinguish different HTTP methods.
- Managing path variables and query parameters becomes error-prone.
3. Solution
Spring Boot’s annotation model solves these problems by providing declarative annotations that map web requests directly to Java methods. These annotations allow developers to specify request paths, HTTP methods, and parameters in a concise and readable way.
@RequestMapping→ defines the base mapping and HTTP method types.@GetMapping,@PostMapping, etc. → simplified versions of@RequestMappingfor specific HTTP methods.@PathVariableand@RequestParam→ extract path and query parameters.@RequestBody→ maps request payloads to Java objects.@ResponseBody→ sends method results back as JSON or XML.
This makes building RESTful services clean, modular, and easy to maintain.
4. Implementation
Let’s walk through an example of a simple Spring Boot REST controller that demonstrates each annotation.
Step 1: Define a Model Class
package com.example.demo.model;
public class Product {
private Long id;
private String name;
private double price;
// Constructors
public Product() {}
public Product(Long id, String name, double price) {
this.id = id;
this.name = name;
this.price = price;
}
// Getters and Setters
public Long getId() { return id; }
public void setId(Long id) { this.id = id; }
public String getName() { return name; }
public void setName(String name) { this.name = name; }
public double getPrice() { return price; }
public void setPrice(double price) { this.price = price; }
}Step 2: Create a REST Controller
package com.example.demo.controller;
import com.example.demo.model.Product;
import org.springframework.web.bind.annotation.*;
import java.util.*;
@RestController
@RequestMapping("/api/products") // Base path for all endpoints in this controller
public class ProductController {
private Map<Long, Product> productRepo = new HashMap<>();
// Sample data
public ProductController() {
productRepo.put(1L, new Product(1L, "Laptop", 1200.00));
productRepo.put(2L, new Product(2L, "Phone", 800.00));
}
// @GetMapping - Retrieve all products
@GetMapping
public Collection<Product> getAllProducts() {
return productRepo.values();
}
// @GetMapping with @PathVariable - Retrieve product by ID
@GetMapping("/{id}")
public Product getProductById(@PathVariable Long id) {
return productRepo.get(id);
}
// @GetMapping with @RequestParam - Filter products by minimum price
@GetMapping("/filter")
public Collection<Product> filterByPrice(@RequestParam double minPrice) {
List<Product> result = new ArrayList<>();
for (Product p : productRepo.values()) {
if (p.getPrice() >= minPrice) result.add(p);
}
return result;
}
// @PostMapping with @RequestBody - Create new product
@PostMapping
public Product createProduct(@RequestBody Product product) {
productRepo.put(product.getId(), product);
return product;
}
// @PutMapping - Update product
@PutMapping("/{id}")
public Product updateProduct(@PathVariable Long id, @RequestBody Product updatedProduct) {
productRepo.put(id, updatedProduct);
return updatedProduct;
}
// @DeleteMapping - Delete product
@DeleteMapping("/{id}")
public String deleteProduct(@PathVariable Long id) {
productRepo.remove(id);
return "Product with ID " + id + " deleted successfully.";
}
}Explanation of Annotations
| Annotation | Description |
|---|---|
@RestController | Combines @Controller and @ResponseBody. Indicates that this class handles REST requests. |
@RequestMapping("/api/products") | Defines the base path for all methods in the controller. |
@GetMapping | Handles HTTP GET requests (data retrieval). |
@PostMapping | Handles HTTP POST requests (data creation). |
@PutMapping | Handles HTTP PUT requests (data updates). |
@DeleteMapping | Handles HTTP DELETE requests (data deletion). |
@PathVariable | Extracts dynamic values from the URI path. |
@RequestParam | Reads query parameters like ?minPrice=100. |
@RequestBody | Maps JSON request bodies to Java objects automatically. |
@ResponseBody | Returns the method’s return value directly as the HTTP response body (applied automatically by @RestController). |
5. Conclusion
Spring Boot’s Web and REST annotations make API development intuitive and efficient. By simply annotating methods, developers can map HTTP requests, handle dynamic paths, process query parameters, and serialize/deserialize request bodies without writing extra boilerplate code.
These annotations are the foundation of modern RESTful microservices built with Spring Boot — keeping controllers clean, readable, and easy to maintain.