Controller Layer
The controller handles incoming HTTP requests and returns responses. It acts as the entry point to your backend.
Controller Annotations
| Annotation | Purpose |
|---|---|
@RestController |
Marks class as a REST controller (combines @Controller + @ResponseBody) |
@RequestMapping("/api/...") |
Base URL path for all endpoints in the class |
@GetMapping |
Handles HTTP GET requests |
@PostMapping |
Handles HTTP POST requests |
@PutMapping |
Handles HTTP PUT requests |
@DeleteMapping |
Handles HTTP DELETE requests |
@PathVariable |
Extracts value from URL path |
@RequestParam |
Extracts query parameters |
@RequestBody |
Deserializes JSON body to Java object |
Complete Controller Example
@RestController
@RequestMapping("/api/users")
public class UserController {
private final UserService userService;
public UserController(UserService userService) {
this.userService = userService;
}
// GET /api/users?page=0&size=10
@GetMapping
public ResponseEntity<Page<UserDto>> getAllUsers(
@RequestParam(defaultValue = "0") int page,
@RequestParam(defaultValue = "10") int size) {
Page<UserDto> users = userService.getAllUsers(PageRequest.of(page, size));
return ResponseEntity.ok(users);
}
// GET /api/users/42
@GetMapping("/{id}")
public ResponseEntity<UserDto> getUser(@PathVariable Long id) {
UserDto user = userService.getUser(id);
return ResponseEntity.ok(user);
}
// POST /api/users
@PostMapping
public ResponseEntity<UserDto> createUser(@Valid @RequestBody CreateUserRequest request) {
UserDto created = userService.createUser(request);
return ResponseEntity.status(HttpStatus.CREATED).body(created);
}
// PUT /api/users/42
@PutMapping("/{id}")
public ResponseEntity<UserDto> updateUser(
@PathVariable Long id,
@Valid @RequestBody UpdateUserRequest request) {
UserDto updated = userService.updateUser(id, request);
return ResponseEntity.ok(updated);
}
// DELETE /api/users/42
@DeleteMapping("/{id}")
public ResponseEntity<Void> deleteUser(@PathVariable Long id) {
userService.deleteUser(id);
return ResponseEntity.noContent().build();
}
}
Best Practices
Key Principles
- Follow SOLID principles
- Write clean, readable code
- Test thoroughly
- Document decisions
- Monitor in production
Implementation
- Start simple, refactor as needed
- Use established patterns
- Consider trade-offs
- Review with peers
Continuous Improvement
- Learn from incidents
- Update documentation
- Share knowledge
- Mentor others
Key Points
- Understanding Controller is essential for production systems
- Always consider scalability and maintainability
- Test thoroughly before deploying to production
- Monitor performance and set up alerting
Common Patterns
- Validation: Always validate input at the boundary
- Error Handling: Use structured error responses
- Logging: Log key events for debugging
- Testing: Unit, integration, and load tests
- Documentation: Keep docs updated with code changes
Practice Problems
Design and implement a solution for Controller in a backend system. Consider scalability, error handling, and production readiness.
Solution
// Controller implementation
// Key aspects: validation, error handling, logging, testing
public class Controller {
// Production-ready implementation
}Identify and handle edge cases for Controller. What happens under high load, with invalid input, or during failures?
Solution
// Edge case handling:
// 1. Null/empty input -> validation
// 2. High load -> rate limiting, queuing
// 3. Failures -> retries, circuit breaker
// 4. Concurrent access -> locks, idempotencyWrite a testing strategy for Controller. Include unit tests, integration tests, and performance tests.
Solution
// Test plan:
// - Unit: 80% coverage target
// - Integration: API contracts
// - Performance: latency, throughput
// - Chaos: failure injectionQuiz
1. What is the purpose of @PathVariable in a Spring controller?
2. What does @RequestParam do in a Spring controller?
3. What is the primary purpose of Controller?
4. What is a common mistake when implementing Controller?
Flashcards
Question
What does @RequestBody do?
Click to reveal answer
Answer
Deserializes the HTTP request body (JSON) to a Java object (DTO)
Question
What HTTP status code should a POST endpoint return when creating a resource?
Click to reveal answer
Answer
201 Created
Question
What is Controller?
Click to reveal answer
Answer
Controller is a key concept in backend development.
Question
When to use Controller?
Click to reveal answer
Answer
Use Controller when building production systems that require reliability, scalability, and maintainability.
Question
Controller best practices
Click to reveal answer
Answer
Follow SOLID principles, write clean code, test thoroughly, document decisions, and monitor in production.
Revision Notes
Key Takeaways
- 1.@RestController combines @Controller and @ResponseBody for REST APIs
- 2.@PathVariable extracts values from URL path segments like /users/{id}
- 3.@RequestParam extracts query parameters like ?page=0&size=10
- 4.@RequestBody deserializes JSON request body to Java objects
- 5.Return ResponseEntity with appropriate HTTP status codes (200 OK, 201 Created, 404 Not Found)
Interview Tips
- •Explain when to use @PathVariable vs @RequestParam with concrete examples
- •Know the common HTTP methods and their corresponding Spring annotations (@GetMapping, @PostMapping, @PutMapping, @DeleteMapping)
- •Discuss RESTful API design principles like proper URL naming and status codes
Cheat Sheet
Controller Layer
- @RestController = @Controller + @ResponseBody
- @RequestMapping("/api/...") sets base path
- @GetMapping, @PostMapping, @PutMapping, @DeleteMapping
- @PathVariable: extract from URL path (/users/{id})
- @RequestParam: extract from query string (?key=value)
- @RequestBody: deserialize JSON to Java object
- Return ResponseEntity with proper HTTP status