REST Controllers in Spring Boot
1. What is a REST Controller?
A REST Controller is responsible for:
- Handling HTTP requests
- Mapping requests to business logic
- Returning HTTP responses (usually JSON)
In Spring Boot:
@RestController
@RequestMapping("/users")
public class UserController {
}
2. @RestController vs @Controller
@RestController
-
Combines:
@Controller@ResponseBody
-
Return JSON directly
@Controller
- Used for MVC (views, JSP, Thymeleaf)
- Requires
@ResponseBodyfor APIs
👉 Always use @RestController for REST APIs
3. Request Mapping Basics
Class Level Mapping
@RequestMapping("/users")
Method Level Mapping
@GetMapping("/{id}")
@PostMapping
@PutMapping("/{id}")
@DeleteMapping("/{id}")
4. Handling Request Inputs
4.1 Path Variables
@GetMapping("/{id}")
public User getUser(@PathVariable Long id) {
return userService.getUser(id);
}
4.2 Query Parameters
@GetMapping
public List<User> getUsers(@RequestParam int page,
@RequestParam int size) {
return userService.getUsers(page, size);
}
4.3 Request Body
@PostMapping
public User createUser(@RequestBody UserRequest request) {
return userService.createUser(request);
}
4.4 Validation
@PostMapping
public User createUser(@Valid @RequestBody UserRequest request) {
return userService.createUser(request);
}
5. Response Handling
5.1 Returning Objects
@GetMapping("/{id}")
public User getUser(@PathVariable Long id) {
return userService.getUser(id);
}
👉 Automatically converted to JSON
5.2 Using ResponseEntity (Recommended)
@GetMapping("/{id}")
public ResponseEntity<User> getUser(@PathVariable Long id) {
return ResponseEntity.ok(userService.getUser(id));
}
5.3 Custom Status Codes
@PostMapping
public ResponseEntity<User> createUser(@RequestBody UserRequest request) {
User user = userService.createUser(request);
return ResponseEntity
.status(HttpStatus.CREATED)
.body(user);
}
6. Controller Layer Responsibilities
✅ Should Do
- Handle HTTP layer
- Validate input
- Call service layer
- Return response
Should NOT Do
- Business logic
- Database access
- Complex transformations
7. Thin Controller Pattern
Bad (Fat Controller)
@PostMapping
public User createUser(@RequestBody UserRequest request) {
// validation logic
// business logic
// DB calls
return user;
}
✅ Good (Thin Controller)
@PostMapping
public ResponseEntity<UserResponse> createUser(@Valid @RequestBody UserRequest request) {
return ResponseEntity.ok(userService.createUser(request));
}
👉 Move logic to Service layer
8. DTO Pattern (Critical)
Why NOT expose entities?
- Security risks
- Tight coupling
- Unwanted fields exposed
Example
Request DTO
public class UserRequest {
private String name;
private String email;
}
Response DTO
public class UserResponse {
private Long id;
private String name;
}
9. API Design in Controllers
Naming
- Use nouns
- Keep endpoints predictable
GET /users
GET /users/{id}
POST /users
DELETE /users/{id}
Versioning
@RequestMapping("/api/v1/users")
10. Exception Handling (Integration)
Controllers should NOT handle exceptions directly.
Avoid:
try {
...
} catch(Exception e) {
return ResponseEntity.status(500).body("error");
}
✅ Use:
@ControllerAdvice(global handling)
11. Content Negotiation
Spring automatically handles:
- JSON (default via Jackson)
You can control:
@GetMapping(produces = MediaType.APPLICATION_JSON_VALUE)
12. Common Mistakes
- Putting business logic in controllers
- Returning entities directly
- Not using DTOs
- Not using ResponseEntity when needed
- Handling exceptions inside controllers
- Overloading controllers with too many responsibilities
13. Real-World Structure
controller/
UserController.java
service/
UserService.java
dto/
UserRequest.java
UserResponse.java
entity/
User.java
repository/
UserRepository.java
14. Summary
- Controllers = HTTP layer only
- Keep them thin
- Use DTOs always
- Delegate logic to services
- Use proper request/response handling
15. Key Takeaway
- 👉 A good controller is boring and simple
- 👉 Complexity belongs in the service layer