07 - Spring MVC and REST Notes
A beginner-to-advanced guide to Spring MVC, controllers, REST APIs, request mapping, validation, exception handling, message converters, REST best practices, interview questions, and a quick cheat sheet for Spring Professional Certification candidates. Covers Spring Framework 6 and Spring Boot 3 concepts.
Table of Contents
- What Is Spring MVC?
- DispatcherServlet and MVC Request Flow
- Controllers
- REST APIs
- Request Mapping
- Reading Request Data
- Producing Responses
- Validation
- Exception Handling
- Message Converters
- Content Negotiation
- REST Best Practices
- Testing Spring MVC and REST Controllers
- Common Mistakes
- Certification Traps
- Interview Questions
- Summary Tables
- One-Page Cheat Sheet
1. What Is Spring MVC?
Spring MVC is Spring's web framework for building web applications and REST APIs. It follows the Model-View-Controller pattern and is built around a central front controller called DispatcherServlet.
Spring MVC can be used for:
| Use Case | Typical Annotation |
|---|---|
| Server-rendered web pages | @Controller |
| REST APIs returning JSON/XML | @RestController |
| Request routing | @RequestMapping, @GetMapping, @PostMapping |
| Request validation | @Valid, @Validated |
| Centralized error handling | @ControllerAdvice, @ExceptionHandler |
MVC Roles
| Role | Responsibility |
|---|---|
| Model | Holds data exposed to the view |
| View | Renders output such as HTML |
| Controller | Handles requests and coordinates the response |
For REST APIs, the view layer is usually replaced by serialized response bodies such as JSON.
2. DispatcherServlet and MVC Request Flow
DispatcherServlet is the front controller in Spring MVC. Every request first reaches the DispatcherServlet, which delegates work to other MVC infrastructure components.
Client
|
v
DispatcherServlet
|
v
HandlerMapping finds matching controller method
|
v
HandlerAdapter invokes controller method
|
v
Controller returns model, view, ResponseEntity, or body
|
v
ViewResolver or HttpMessageConverter prepares response
|
v
HTTP response sent to client
Important MVC Components
| Component | Purpose |
|---|---|
DispatcherServlet | Central request dispatcher |
HandlerMapping | Finds the controller method for a request |
HandlerAdapter | Invokes the selected controller method |
ViewResolver | Resolves logical view names to actual views |
HttpMessageConverter | Converts request/response bodies |
HandlerExceptionResolver | Resolves exceptions into responses |
In Spring Boot, Spring MVC is auto-configured when spring-boot-starter-web is on the classpath.
3. Controllers
Controllers are Spring beans that handle web requests.
@Controller
@Controller is used for MVC applications that return views.
@Controller
class PageController {
@GetMapping("/home")
String home(Model model) {
model.addAttribute("title", "Home");
return "home";
}
}
The returned string is treated as a logical view name.
@RestController
@RestController is used for REST APIs.
@RestController
@RequestMapping("/api/products")
class ProductController {
private final ProductService productService;
ProductController(ProductService productService) {
this.productService = productService;
}
@GetMapping("/{id}")
ProductResponse findById(@PathVariable Long id) {
return productService.findById(id);
}
}
@RestController combines:
@Controller
@ResponseBody
This means return values are written directly to the HTTP response body.
Controller Stereotype Comparison
| Annotation | Returns | Common Use |
|---|---|---|
@Controller | Views by default | HTML web apps |
@RestController | Response body by default | REST APIs |
@ResponseBody | Response body for one method/class | JSON/XML output |
4. REST APIs
REST APIs expose resources over HTTP using standard HTTP methods, URIs, status codes, and representations.
Resource Example
For an order resource:
| Operation | HTTP Method | URI |
|---|---|---|
| List orders | GET | /api/orders |
| Get one order | GET | /api/orders/{id} |
| Create order | POST | /api/orders |
| Replace order | PUT | /api/orders/{id} |
| Partially update order | PATCH | /api/orders/{id} |
| Delete order | DELETE | /api/orders/{id} |
Example REST Controller
@RestController
@RequestMapping("/api/orders")
class OrderController {
private final OrderService orderService;
OrderController(OrderService orderService) {
this.orderService = orderService;
}
@GetMapping("/{id}")
ResponseEntity<OrderResponse> getOrder(@PathVariable Long id) {
return ResponseEntity.ok(orderService.getOrder(id));
}
@PostMapping
ResponseEntity<OrderResponse> createOrder(@Valid @RequestBody CreateOrderRequest request) {
OrderResponse created = orderService.createOrder(request);
URI location = URI.create("/api/orders/" + created.id());
return ResponseEntity.created(location).body(created);
}
@DeleteMapping("/{id}")
ResponseEntity<Void> deleteOrder(@PathVariable Long id) {
orderService.deleteOrder(id);
return ResponseEntity.noContent().build();
}
}
Common REST Status Codes
| Status | Meaning | Typical Use |
|---|---|---|
200 OK | Request succeeded | Successful GET, PUT, PATCH |
201 Created | Resource created | Successful POST |
204 No Content | Success with no body | Successful DELETE |
400 Bad Request | Invalid request | Validation or malformed input |
401 Unauthorized | Not authenticated | Missing or invalid credentials |
403 Forbidden | Authenticated but not allowed | Access denied |
404 Not Found | Resource does not exist | Missing entity |
409 Conflict | State conflict | Duplicate or invalid state transition |
415 Unsupported Media Type | Unsupported request body format | Wrong Content-Type |
500 Internal Server Error | Unexpected server error | Unhandled exception |
5. Request Mapping
Request mapping connects HTTP requests to controller methods.
@RequestMapping
@RequestMapping can be used at class or method level.
@RestController
@RequestMapping("/api/customers")
class CustomerController {
@RequestMapping(method = RequestMethod.GET)
List<CustomerResponse> findAll() {
return List.of();
}
}
Shortcut Mapping Annotations
| Annotation | Equivalent |
|---|---|
@GetMapping | @RequestMapping(method = RequestMethod.GET) |
@PostMapping | @RequestMapping(method = RequestMethod.POST) |
@PutMapping | @RequestMapping(method = RequestMethod.PUT) |
@PatchMapping | @RequestMapping(method = RequestMethod.PATCH) |
@DeleteMapping | @RequestMapping(method = RequestMethod.DELETE) |
Path Variables
Use @PathVariable for values embedded in the URI path.
@GetMapping("/customers/{customerId}/orders/{orderId}")
OrderResponse findOrder(
@PathVariable Long customerId,
@PathVariable Long orderId) {
return orderService.findOrder(customerId, orderId);
}
Query Parameters
Use @RequestParam for query string values.
@GetMapping("/products")
List<ProductResponse> search(
@RequestParam(required = false) String category,
@RequestParam(defaultValue = "0") int page,
@RequestParam(defaultValue = "20") int size) {
return productService.search(category, page, size);
}
Request:
GET /products?category=books&page=1&size=10
Headers
Use @RequestHeader to read HTTP headers.
@GetMapping("/profile")
ProfileResponse profile(@RequestHeader("X-Correlation-Id") String correlationId) {
return profileService.load(correlationId);
}
Cookies
Use @CookieValue to read cookie values.
@GetMapping("/preferences")
PreferenceResponse preferences(@CookieValue("theme") String theme) {
return new PreferenceResponse(theme);
}
Mapping by consumes and produces
@PostMapping(
value = "/documents",
consumes = MediaType.APPLICATION_JSON_VALUE,
produces = MediaType.APPLICATION_JSON_VALUE)
DocumentResponse create(@RequestBody DocumentRequest request) {
return documentService.create(request);
}
| Attribute | Purpose |
|---|---|
value or path | URI pattern |
method | HTTP method |
params | Required request parameters |
headers | Required request headers |
consumes | Supported request media type |
produces | Response media type |
6. Reading Request Data
Spring MVC provides annotations for binding different parts of an HTTP request.
Request Body
Use @RequestBody to bind the HTTP body to a Java object.
record CreateUserRequest(
String name,
String email
) {
}
@PostMapping("/users")
UserResponse createUser(@RequestBody CreateUserRequest request) {
return userService.create(request);
}
@RequestBody commonly uses Jackson to convert JSON into Java objects.
Form and Query Binding with @ModelAttribute
@ModelAttribute binds request parameters to an object.
class ProductSearchForm {
private String keyword;
private BigDecimal minPrice;
private BigDecimal maxPrice;
// getters and setters
}
@GetMapping("/products/search")
String search(@ModelAttribute ProductSearchForm form, Model model) {
model.addAttribute("products", productService.search(form));
return "products";
}
Common Request Binding Annotations
| Annotation | Reads From | Example |
|---|---|---|
@PathVariable | URI path | /orders/{id} |
@RequestParam | Query string or form data | ?page=1 |
@RequestHeader | HTTP header | Accept-Language |
@CookieValue | Cookie | SESSION |
@RequestBody | HTTP body | JSON payload |
@ModelAttribute | Request parameters | Form object |
7. Producing Responses
Spring MVC supports several response styles.
Returning a Body Directly
@GetMapping("/health")
Map<String, String> health() {
return Map.of("status", "UP");
}
In a @RestController, this object is serialized to JSON by an HttpMessageConverter.
Using ResponseEntity
ResponseEntity gives full control over status, headers, and body.
@GetMapping("/users/{id}")
ResponseEntity<UserResponse> findUser(@PathVariable Long id) {
return userService.findUser(id)
.map(ResponseEntity::ok)
.orElseGet(() -> ResponseEntity.notFound().build());
}
Returning Views
@Controller
class LoginController {
@GetMapping("/login")
String loginPage() {
return "login";
}
}
Response Options
| Return Type | Use Case |
|---|---|
String in @Controller | Logical view name |
Object in @RestController | JSON/XML response body |
ResponseEntity<T> | Status, headers, and body control |
void | Response handled manually or no content |
ModelAndView | View and model together |
8. Validation
Spring MVC integrates with Bean Validation through Jakarta Validation.
In Spring Boot 3 and Spring Framework 6, validation uses the jakarta.validation package.
Dependency
Spring Boot applications usually add:
spring-boot-starter-validation
DTO Validation
import jakarta.validation.constraints.Email;
import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.Size;
record CreateCustomerRequest(
@NotBlank(message = "Name is required")
@Size(max = 100, message = "Name must not exceed 100 characters")
String name,
@NotBlank(message = "Email is required")
@Email(message = "Email must be valid")
String email
) {
}
Triggering Validation
@PostMapping("/customers")
ResponseEntity<CustomerResponse> createCustomer(
@Valid @RequestBody CreateCustomerRequest request) {
CustomerResponse created = customerService.create(request);
return ResponseEntity.status(HttpStatus.CREATED).body(created);
}
If validation fails, Spring throws MethodArgumentNotValidException.
Validating Path Variables and Request Parameters
Use @Validated on the controller class.
@Validated
@RestController
@RequestMapping("/api/invoices")
class InvoiceController {
@GetMapping
List<InvoiceResponse> findInvoices(
@RequestParam @Min(1) int page,
@RequestParam @Max(100) int size) {
return invoiceService.findInvoices(page, size);
}
}
Common Validation Annotations
| Annotation | Purpose |
|---|---|
@NotNull | Value must not be null |
@NotBlank | String must contain non-whitespace text |
@NotEmpty | Collection, array, map, or string must not be empty |
@Size | Size must be within bounds |
@Min, @Max | Numeric bounds |
@Positive, @PositiveOrZero | Positive numeric values |
@Email | Valid email format |
@Pattern | Regular expression match |
@Past, @Future | Date/time constraints |
@Valid | Cascade validation to nested object |
Validation Error Response Example
{
"status": 400,
"error": "Validation failed",
"fieldErrors": {
"email": "Email must be valid",
"name": "Name is required"
}
}
9. Exception Handling
Spring MVC provides local and global exception handling.
Local Exception Handling with @ExceptionHandler
@RestController
@RequestMapping("/api/products")
class ProductController {
@GetMapping("/{id}")
ProductResponse findById(@PathVariable Long id) {
return productService.findById(id);
}
@ExceptionHandler(ProductNotFoundException.class)
ResponseEntity<ApiError> handleProductNotFound(ProductNotFoundException ex) {
return ResponseEntity.status(HttpStatus.NOT_FOUND)
.body(new ApiError("PRODUCT_NOT_FOUND", ex.getMessage()));
}
}
This handler applies only to the controller where it is declared.
Global Exception Handling with @ControllerAdvice
@RestControllerAdvice
class GlobalExceptionHandler {
@ExceptionHandler(CustomerNotFoundException.class)
ResponseEntity<ApiError> handleCustomerNotFound(CustomerNotFoundException ex) {
return ResponseEntity.status(HttpStatus.NOT_FOUND)
.body(new ApiError("CUSTOMER_NOT_FOUND", ex.getMessage()));
}
@ExceptionHandler(MethodArgumentNotValidException.class)
ResponseEntity<ValidationErrorResponse> handleValidation(MethodArgumentNotValidException ex) {
Map<String, String> fieldErrors = new LinkedHashMap<>();
for (FieldError fieldError : ex.getBindingResult().getFieldErrors()) {
fieldErrors.put(fieldError.getField(), fieldError.getDefaultMessage());
}
return ResponseEntity.badRequest()
.body(new ValidationErrorResponse("VALIDATION_FAILED", fieldErrors));
}
}
@RestControllerAdvice combines:
@ControllerAdvice
@ResponseBody
ResponseStatusException
Use ResponseStatusException for simple HTTP errors.
@GetMapping("/accounts/{id}")
AccountResponse findAccount(@PathVariable Long id) {
return accountService.findById(id)
.orElseThrow(() -> new ResponseStatusException(
HttpStatus.NOT_FOUND,
"Account not found"));
}
@ResponseStatus
Custom exceptions can declare a fixed HTTP status.
@ResponseStatus(HttpStatus.NOT_FOUND)
class OrderNotFoundException extends RuntimeException {
OrderNotFoundException(String message) {
super(message);
}
}
This is simple, but less flexible than @ControllerAdvice.
Problem Details
Spring Framework 6 supports RFC 7807 problem details through ProblemDetail.
@ExceptionHandler(OrderNotFoundException.class)
ProblemDetail handleOrderNotFound(OrderNotFoundException ex) {
ProblemDetail problem = ProblemDetail.forStatus(HttpStatus.NOT_FOUND);
problem.setTitle("Order not found");
problem.setDetail(ex.getMessage());
return problem;
}
Example response:
{
"type": "about:blank",
"title": "Order not found",
"status": 404,
"detail": "Order 10 was not found"
}
Exception Handling Options
| Option | Scope | Best For |
|---|---|---|
@ExceptionHandler in controller | One controller | Local handling |
@ControllerAdvice | Multiple controllers | Global MVC handling |
@RestControllerAdvice | Multiple REST controllers | Global REST errors |
@ResponseStatus | Exception class | Fixed status mapping |
ResponseStatusException | One throw site | Simple programmatic errors |
ProblemDetail | Error response body | Standardized REST error format |
10. Message Converters
HttpMessageConverter converts HTTP request bodies into Java objects and Java objects into HTTP response bodies.
Where Message Converters Are Used
| Scenario | Converter Role |
|---|---|
@RequestBody | Convert request JSON/XML/text into Java object |
@ResponseBody | Convert Java object into JSON/XML/text response |
@RestController return value | Convert return value into response body |
ResponseEntity<T> body | Convert body into response representation |
Common Message Converters
| Converter | Media Type | Purpose |
|---|---|---|
MappingJackson2HttpMessageConverter | application/json | JSON with Jackson |
StringHttpMessageConverter | text/plain | Plain text |
ByteArrayHttpMessageConverter | application/octet-stream | Binary data |
ResourceHttpMessageConverter | Resource media types | File/resource responses |
AllEncompassingFormHttpMessageConverter | Form data | HTML form and multipart support |
JSON Conversion Example
Request:
POST /api/books
Content-Type: application/json
Accept: application/json
{
"title": "Spring in Action",
"author": "Craig Walls"
}
Controller:
@PostMapping("/books")
BookResponse createBook(@RequestBody CreateBookRequest request) {
return bookService.create(request);
}
Converter behavior:
JSON request body -> CreateBookRequest
BookResponse -> JSON response body
Customizing Converters
Spring Boot auto-configures converters, especially Jackson for JSON. You can customize JSON behavior through properties or beans.
spring.jackson.serialization.indent-output=true
spring.jackson.default-property-inclusion=non_null
For advanced MVC customization:
@Configuration
class WebConfig implements WebMvcConfigurer {
@Override
public void extendMessageConverters(List<HttpMessageConverter<?>> converters) {
// Add or customize converters without replacing Spring Boot defaults.
}
}
Prefer extendMessageConverters over configureMessageConverters when using Spring Boot, because configureMessageConverters can replace the default converter list.
11. Content Negotiation
Content negotiation decides which representation should be returned for a request.
Common Headers
| Header | Meaning |
|---|---|
Content-Type | Format of the request body |
Accept | Format the client wants in the response |
Example:
POST /api/orders
Content-Type: application/json
Accept: application/json
consumes
consumes restricts the request body media type.
@PostMapping(value = "/reports", consumes = MediaType.APPLICATION_JSON_VALUE)
ReportResponse createReport(@RequestBody ReportRequest request) {
return reportService.create(request);
}
If the client sends an unsupported Content-Type, Spring can return 415 Unsupported Media Type.
produces
produces restricts the response media type.
@GetMapping(value = "/reports/{id}", produces = MediaType.APPLICATION_JSON_VALUE)
ReportResponse findReport(@PathVariable Long id) {
return reportService.findById(id);
}
If the server cannot produce an acceptable response for the client's Accept header, Spring can return 406 Not Acceptable.
12. REST Best Practices
URI Design
Use nouns for resources, not verbs.
| Prefer | Avoid |
|---|---|
GET /api/orders/10 | GET /api/getOrder?id=10 |
POST /api/orders | POST /api/createOrder |
DELETE /api/orders/10 | POST /api/deleteOrder |
HTTP Method Semantics
| Method | Safe? | Idempotent? | Purpose |
|---|---|---|---|
GET | Yes | Yes | Read |
POST | No | No | Create or process |
PUT | No | Yes | Replace |
PATCH | No | Usually no | Partial update |
DELETE | No | Yes | Delete |
Status Code Usage
| Situation | Recommended Status |
|---|---|
| Resource created | 201 Created with Location header |
| Delete succeeded | 204 No Content |
| Validation failed | 400 Bad Request |
| Resource missing | 404 Not Found |
| Duplicate resource | 409 Conflict |
| Authentication required | 401 Unauthorized |
| Access denied | 403 Forbidden |
DTOs Over Entities
Do not expose JPA entities directly from controllers.
Prefer:
record ProductResponse(
Long id,
String name,
BigDecimal price
) {
}
Avoid:
@GetMapping("/products/{id}")
ProductEntity findProduct(@PathVariable Long id) {
return repository.findById(id).orElseThrow();
}
Reasons:
- Prevents accidental exposure of internal fields.
- Avoids lazy loading and serialization issues.
- Keeps API contracts stable.
- Separates persistence model from API model.
Pagination and Sorting
Use query parameters for pagination and sorting.
GET /api/products?page=0&size=20&sort=name,asc
Spring Data example:
@GetMapping("/products")
Page<ProductResponse> findProducts(Pageable pageable) {
return productService.findProducts(pageable);
}
Versioning
Common versioning options:
| Strategy | Example |
|---|---|
| URI versioning | /api/v1/orders |
| Header versioning | X-API-Version: 1 |
| Media type versioning | Accept: application/vnd.example.v1+json |
URI versioning is simple and common, but version only when necessary.
Error Response Consistency
Use one consistent error format.
{
"code": "ORDER_NOT_FOUND",
"message": "Order was not found",
"timestamp": "2026-06-30T18:00:00Z",
"path": "/api/orders/99"
}
Security-Aware API Design
- Validate all input.
- Do not expose stack traces to clients.
- Do not leak sensitive fields in DTOs.
- Use HTTPS in production.
- Protect state-changing operations.
- Use proper authentication and authorization.
- Log enough for support, but avoid logging secrets.
13. Testing Spring MVC and REST Controllers
Spring Boot provides @WebMvcTest for focused MVC tests.
@WebMvcTest(ProductController.class)
class ProductControllerTest {
@Autowired
private MockMvc mockMvc;
@MockBean
private ProductService productService;
@Test
void shouldReturnProduct() throws Exception {
given(productService.findById(1L))
.willReturn(new ProductResponse(1L, "Keyboard"));
mockMvc.perform(get("/api/products/1"))
.andExpect(status().isOk())
.andExpect(jsonPath("$.name").value("Keyboard"));
}
}
Testing Options
| Tool | Purpose |
|---|---|
MockMvc | Server-side MVC testing without real HTTP server |
@WebMvcTest | Slice test for controllers and MVC infrastructure |
@SpringBootTest | Full application context integration test |
TestRestTemplate | HTTP client for integration tests |
WebTestClient | Reactive-style test client; can test MVC too |
14. Common Mistakes
| Mistake | Better Approach |
|---|---|
| Returning entities directly | Return DTOs |
Using POST for every operation | Use correct HTTP methods |
| Ignoring validation | Use @Valid and constraint annotations |
| Catching all exceptions in controllers | Use targeted global exception handling |
Returning 200 OK for resource creation | Return 201 Created |
Returning a body with 204 No Content | Use empty body |
| Mixing view controllers and REST APIs accidentally | Use @Controller and @RestController intentionally |
| Replacing all message converters in Boot | Use extendMessageConverters |
| Exposing technical error details | Return safe, consistent error responses |
15. Certification Traps
Trap 1: @Controller vs @RestController
@Controller does not automatically serialize return values as response bodies. Use @ResponseBody or @RestController.
Trap 2: @RequestBody vs @RequestParam
@RequestBody reads the HTTP body. @RequestParam reads query parameters or form parameters.
Trap 3: Content-Type vs Accept
Content-Type describes what the client sends. Accept describes what the client wants back.
Trap 4: Validation Requires @Valid
Constraint annotations on a request DTO are not enough. The controller parameter must use @Valid or @Validated.
Trap 5: @ControllerAdvice Is Not Limited to REST
@ControllerAdvice applies to controllers generally. @RestControllerAdvice is convenient for REST because it includes @ResponseBody.
Trap 6: Message Converters Are Not View Resolvers
Message converters serialize response bodies. View resolvers resolve view names for server-rendered pages.
16. Interview Questions
1. What is Spring MVC?
Spring MVC is Spring's web framework based on the Model-View-Controller pattern. It uses DispatcherServlet as a front controller to route requests to controller methods and produce responses through views or message converters.
2. What is the role of DispatcherServlet?
DispatcherServlet receives incoming requests, finds the appropriate handler using HandlerMapping, invokes it through HandlerAdapter, and coordinates view rendering, message conversion, or exception handling.
3. Difference between @Controller and @RestController?
@Controller is used mainly for MVC views. @RestController is equivalent to @Controller plus @ResponseBody, so return values are written directly to the HTTP response body.
4. What is @RequestMapping?
@RequestMapping maps HTTP requests to controller classes or methods based on path, method, headers, parameters, consumes, and produces.
5. Difference between @PathVariable and @RequestParam?
@PathVariable extracts values from the URI path, while @RequestParam extracts values from query parameters or form parameters.
6. What does @RequestBody do?
@RequestBody binds the HTTP request body to a Java object using an HttpMessageConverter, commonly Jackson for JSON.
7. What does @ResponseBody do?
@ResponseBody tells Spring to write the return value directly to the HTTP response body instead of resolving it as a view name.
8. What is ResponseEntity?
ResponseEntity represents the full HTTP response, including status code, headers, and body. It is useful when a controller needs explicit response control.
9. How does validation work in Spring MVC?
Spring MVC integrates with Jakarta Bean Validation. Add constraints to DTO fields and use @Valid or @Validated on controller parameters to trigger validation.
10. What happens when validation fails?
For invalid @RequestBody arguments, Spring usually throws MethodArgumentNotValidException, which can be handled globally using @ExceptionHandler inside @ControllerAdvice or @RestControllerAdvice.
11. How do you handle exceptions globally in REST APIs?
Create a class annotated with @RestControllerAdvice and define methods annotated with @ExceptionHandler for specific exception types.
12. What are message converters?
HttpMessageConverter implementations convert request bodies to Java objects and Java objects to response bodies. JSON conversion is commonly handled by MappingJackson2HttpMessageConverter.
13. What is content negotiation?
Content negotiation is the process of choosing the request and response representation based on headers such as Content-Type and Accept, plus controller mapping rules such as consumes and produces.
14. Difference between PUT and PATCH?
PUT usually replaces an entire resource and is idempotent. PATCH applies a partial update and may or may not be idempotent depending on implementation.
15. Why should REST controllers use DTOs instead of entities?
DTOs protect internal data, prevent accidental field exposure, avoid persistence serialization problems, and keep the API contract independent of the database model.
17. Summary Tables
Core Annotations
| Annotation | Purpose |
|---|---|
@Controller | MVC controller, usually returns views |
@RestController | REST controller, returns response bodies |
@RequestMapping | General request mapping |
@GetMapping | Maps HTTP GET |
@PostMapping | Maps HTTP POST |
@PutMapping | Maps HTTP PUT |
@PatchMapping | Maps HTTP PATCH |
@DeleteMapping | Maps HTTP DELETE |
@ResponseBody | Writes return value to response body |
@RequestBody | Reads request body |
@ResponseStatus | Sets fixed response status |
@ControllerAdvice | Global MVC advice |
@RestControllerAdvice | Global REST advice |
@ExceptionHandler | Handles exceptions |
Request Data Annotations
| Annotation | Source |
|---|---|
@PathVariable | URI path |
@RequestParam | Query string or form parameter |
@RequestHeader | HTTP header |
@CookieValue | Cookie |
@RequestBody | HTTP request body |
@ModelAttribute | Request parameters bound to object |
REST Method Summary
| Method | Typical Operation | Request Body? | Response |
|---|---|---|---|
GET | Read resource | No | 200 OK |
POST | Create resource | Yes | 201 Created |
PUT | Replace resource | Yes | 200 OK or 204 No Content |
PATCH | Partial update | Yes | 200 OK or 204 No Content |
DELETE | Delete resource | Usually no | 204 No Content |
18. One-Page Cheat Sheet
Controller Basics
@RestController
@RequestMapping("/api/items")
class ItemController {
@GetMapping("/{id}")
ItemResponse findById(@PathVariable Long id) {
return itemService.findById(id);
}
@PostMapping
ResponseEntity<ItemResponse> create(@Valid @RequestBody CreateItemRequest request) {
ItemResponse created = itemService.create(request);
return ResponseEntity.status(HttpStatus.CREATED).body(created);
}
}
Mapping Quick Reference
| Need | Use |
|---|---|
| URI path value | @PathVariable |
| Query parameter | @RequestParam |
| Header value | @RequestHeader |
| Cookie value | @CookieValue |
| JSON request body | @RequestBody |
| Validate body | @Valid @RequestBody |
| Return status and headers | ResponseEntity |
| Global REST errors | @RestControllerAdvice |
Validation Quick Reference
record RegisterUserRequest(
@NotBlank String name,
@Email String email,
@Size(min = 8) String password
) {
}
@PostMapping("/users")
ResponseEntity<UserResponse> register(@Valid @RequestBody RegisterUserRequest request) {
return ResponseEntity.status(HttpStatus.CREATED).body(userService.register(request));
}
Exception Handling Quick Reference
@RestControllerAdvice
class ApiExceptionHandler {
@ExceptionHandler(ResourceNotFoundException.class)
ResponseEntity<ApiError> handleNotFound(ResourceNotFoundException ex) {
return ResponseEntity.status(HttpStatus.NOT_FOUND)
.body(new ApiError("NOT_FOUND", ex.getMessage()));
}
}
Message Converter Quick Reference
@RequestBody -> HTTP body to Java object
@ResponseBody -> Java object to HTTP body
Jackson -> JSON converter used by default in Spring Boot web apps
Best Practice Checklist
- Use nouns in URIs.
- Use correct HTTP methods.
- Return appropriate HTTP status codes.
- Use DTOs for requests and responses.
- Validate input with Bean Validation.
- Centralize exception handling.
- Keep error responses consistent.
- Do not expose stack traces or internal model details.
- Use
ResponseEntitywhen status or headers matter. - Prefer
@RestControllerAdvicefor REST API errors.