Welcome to the lecture where we'll start diving into building REST APIs with Spring! Today we'll focus specifically on REST controllers, which are the backbone of working with REST APIs. If you've wanted to build your first real client-server interaction, this lecture is for you.
What is a REST controller in Spring?
A REST controller in Spring is a component that handles HTTP requests (GET, POST, PUT, DELETE, etc.) and returns data to the client in the required format (usually JSON). A controller is the "glue" between the client and the server-side parts of your app, like services and repositories.
The key point is using the @RestController annotation. It tells Spring that this class will handle HTTP requests and return data in JSON (or another) format (XML, text, etc.).
@RestController combines the functionality of two annotations:
@Controller (marks the class as a controller) and
@ResponseBody (indicates that data is returned in the HTTP response body rather than via a view).
Difference between @Controller and @RestController
To make it clearer, let's break down the difference between these annotations:
| Annotation | Main purpose |
|---|---|
@Controller |
Used to generate HTML pages with template engines like Thymeleaf or JSP |
@RestController |
Designed for building REST APIs, returns data (mostly JSON). All methods implicitly include @ResponseBody |
If you need to interact with the client via JSON — for example, for mobile apps or SPAs (Single Page Applications) — @RestController is your go-to. It removes the extra view work so you can focus on the data.
Setting up a basic REST controller
Step 1: Create a new controller class
So, let's create a basic REST controller to handle requests. Imagine we have an entity Customer and we want to manage data for that entity.
package com.example.demo.controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
@RequestMapping("/api/customers")
public class CustomerController {
@GetMapping
public String getAllCustomers() {
return "Here's the list of customers!";
}
}
@RestController: Mark the class as a REST controller.@RequestMapping("/api/customers"): Define the base path (URI) for all customer-related requests.@GetMapping: Indicates the method handles HTTP GET requests.- Returning a string: This is a temporary example — we'll replace the string with real objects later.
Now, if you run the app and open your browser at http://localhost:8080/api/customers, you'll see: Here's the list of customers!.
Step 2: Returning data as JSON
REST APIs typically return data in JSON. In the Spring world this is handled by the Jackson library, which automatically converts Java objects to JSON and back.
Let's modify our example to return a list of customers:
package com.example.demo.controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.List;
@RestController
@RequestMapping("/api/customers")
public class CustomerController {
@GetMapping
public List<String> getAllCustomers() {
return List.of("Ivan Ivanov", "Petr Petrov", "Svetlana Smirnova");
}
}
Now, if you hit http://localhost:8080/api/customers again, you'll get the following JSON:
[
"Ivan Ivanov",
"Petr Petrov",
"Svetlana Smirnova"
]
What happened?
- We returned a list of strings with customer names.
- Jackson automatically converted the
List<String>into a JSON array.
Route configuration using annotations
Main routing annotations
Spring gives you handy annotations for working with different HTTP methods:
| Annotation | Description | Example |
|---|---|---|
@GetMapping |
Handles GET requests | Getting a list or a single resource |
@PostMapping |
Handles POST requests | Creating a new resource |
@PutMapping |
Handles PUT requests | Full update of an existing resource |
@DeleteMapping |
Handles DELETE requests | Deleting a resource |
@PatchMapping |
Handles PATCH requests | Partial update of a resource |
Example: working with CRUD operations
Let's build a full controller to manage customers using all the HTTP methods listed above. For simplicity we'll keep data in memory for now:
package com.example.demo.controller;
import org.springframework.web.bind.annotation.*;
import java.util.ArrayList;
import java.util.List;
@RestController
@RequestMapping("/api/customers")
public class CustomerController {
private final List<String> customers = new ArrayList<>(List.of("Ivan Ivanov", "Petr Petrov"));
@GetMapping
public List<String> getAllCustomers() {
return customers;
}
@PostMapping
public String addCustomer(@RequestBody String customer) {
customers.add(customer);
return "Customer added: " + customer;
}
@PutMapping("/{index}")
public String updateCustomer(@PathVariable int index, @RequestBody String customer) {
customers.set(index, customer);
return "Customer updated: " + customer;
}
@DeleteMapping("/{index}")
public String deleteCustomer(@PathVariable int index) {
String removed = customers.remove(index);
return "Customer deleted: " + removed;
}
}
- Working with HTTP methods: we created methods for all CRUD operations.
@RequestBody: used to get data from the request body (e.g., POST or PUT).@PathVariable: extracts path parameters (e.g., the customer's index in the list).
Testing the controller
Adding a new customer:
curl -X POST -H "Content-Type: application/json" -d "Svetlana Smirnova" http://localhost:8080/api/customers
Response:
Customer added: Svetlana Smirnova
Updating a customer:
curl -X PUT -H "Content-Type: application/json" -d "Mikhail Mikhailov" http://localhost:8080/api/customers/0
Response:
Customer updated: Mikhail Mikhailov
Deleting a customer:
curl -X DELETE http://localhost:8080/api/customers/1
Response:
Customer deleted: Petr Petrov
Benefits and practical uses
Today you learned how to create REST controllers using @RestController. This is a fundamental skill for working with REST APIs. You'll use it all the time, whether you're building a microservice, an API for a mobile app, or a full web application.
Common mistakes
One common mistake is forgetting to add @RestController or @ResponseBody. In that case Spring won't produce JSON responses, and the client might get an empty body or a 404.
Another frequent issue is misconfigured paths (URIs), so requests don't reach the intended method. Always make sure to use precise route annotations like @GetMapping or @PostMapping.
GO TO FULL VERSION