MindIQ Academy

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

  1. What Is Spring MVC?
  2. DispatcherServlet and MVC Request Flow
  3. Controllers
  4. REST APIs
  5. Request Mapping
  6. Reading Request Data
  7. Producing Responses
  8. Validation
  9. Exception Handling
  10. Message Converters
  11. Content Negotiation
  12. REST Best Practices
  13. Testing Spring MVC and REST Controllers
  14. Common Mistakes
  15. Certification Traps
  16. Interview Questions
  17. Summary Tables
  18. 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 CaseTypical 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

RoleResponsibility
ModelHolds data exposed to the view
ViewRenders output such as HTML
ControllerHandles 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

ComponentPurpose
DispatcherServletCentral request dispatcher
HandlerMappingFinds the controller method for a request
HandlerAdapterInvokes the selected controller method
ViewResolverResolves logical view names to actual views
HttpMessageConverterConverts request/response bodies
HandlerExceptionResolverResolves 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

AnnotationReturnsCommon Use
@ControllerViews by defaultHTML web apps
@RestControllerResponse body by defaultREST APIs
@ResponseBodyResponse body for one method/classJSON/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:

OperationHTTP MethodURI
List ordersGET/api/orders
Get one orderGET/api/orders/{id}
Create orderPOST/api/orders
Replace orderPUT/api/orders/{id}
Partially update orderPATCH/api/orders/{id}
Delete orderDELETE/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

StatusMeaningTypical Use
200 OKRequest succeededSuccessful GET, PUT, PATCH
201 CreatedResource createdSuccessful POST
204 No ContentSuccess with no bodySuccessful DELETE
400 Bad RequestInvalid requestValidation or malformed input
401 UnauthorizedNot authenticatedMissing or invalid credentials
403 ForbiddenAuthenticated but not allowedAccess denied
404 Not FoundResource does not existMissing entity
409 ConflictState conflictDuplicate or invalid state transition
415 Unsupported Media TypeUnsupported request body formatWrong Content-Type
500 Internal Server ErrorUnexpected server errorUnhandled 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

AnnotationEquivalent
@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);
}
AttributePurpose
value or pathURI pattern
methodHTTP method
paramsRequired request parameters
headersRequired request headers
consumesSupported request media type
producesResponse 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

AnnotationReads FromExample
@PathVariableURI path/orders/{id}
@RequestParamQuery string or form data?page=1
@RequestHeaderHTTP headerAccept-Language
@CookieValueCookieSESSION
@RequestBodyHTTP bodyJSON payload
@ModelAttributeRequest parametersForm 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 TypeUse Case
String in @ControllerLogical view name
Object in @RestControllerJSON/XML response body
ResponseEntity<T>Status, headers, and body control
voidResponse handled manually or no content
ModelAndViewView 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

AnnotationPurpose
@NotNullValue must not be null
@NotBlankString must contain non-whitespace text
@NotEmptyCollection, array, map, or string must not be empty
@SizeSize must be within bounds
@Min, @MaxNumeric bounds
@Positive, @PositiveOrZeroPositive numeric values
@EmailValid email format
@PatternRegular expression match
@Past, @FutureDate/time constraints
@ValidCascade 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

OptionScopeBest For
@ExceptionHandler in controllerOne controllerLocal handling
@ControllerAdviceMultiple controllersGlobal MVC handling
@RestControllerAdviceMultiple REST controllersGlobal REST errors
@ResponseStatusException classFixed status mapping
ResponseStatusExceptionOne throw siteSimple programmatic errors
ProblemDetailError response bodyStandardized 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

ScenarioConverter Role
@RequestBodyConvert request JSON/XML/text into Java object
@ResponseBodyConvert Java object into JSON/XML/text response
@RestController return valueConvert return value into response body
ResponseEntity<T> bodyConvert body into response representation

Common Message Converters

ConverterMedia TypePurpose
MappingJackson2HttpMessageConverterapplication/jsonJSON with Jackson
StringHttpMessageConvertertext/plainPlain text
ByteArrayHttpMessageConverterapplication/octet-streamBinary data
ResourceHttpMessageConverterResource media typesFile/resource responses
AllEncompassingFormHttpMessageConverterForm dataHTML 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

HeaderMeaning
Content-TypeFormat of the request body
AcceptFormat 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.

PreferAvoid
GET /api/orders/10GET /api/getOrder?id=10
POST /api/ordersPOST /api/createOrder
DELETE /api/orders/10POST /api/deleteOrder

HTTP Method Semantics

MethodSafe?Idempotent?Purpose
GETYesYesRead
POSTNoNoCreate or process
PUTNoYesReplace
PATCHNoUsually noPartial update
DELETENoYesDelete

Status Code Usage

SituationRecommended Status
Resource created201 Created with Location header
Delete succeeded204 No Content
Validation failed400 Bad Request
Resource missing404 Not Found
Duplicate resource409 Conflict
Authentication required401 Unauthorized
Access denied403 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:

StrategyExample
URI versioning/api/v1/orders
Header versioningX-API-Version: 1
Media type versioningAccept: 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

ToolPurpose
MockMvcServer-side MVC testing without real HTTP server
@WebMvcTestSlice test for controllers and MVC infrastructure
@SpringBootTestFull application context integration test
TestRestTemplateHTTP client for integration tests
WebTestClientReactive-style test client; can test MVC too

14. Common Mistakes

MistakeBetter Approach
Returning entities directlyReturn DTOs
Using POST for every operationUse correct HTTP methods
Ignoring validationUse @Valid and constraint annotations
Catching all exceptions in controllersUse targeted global exception handling
Returning 200 OK for resource creationReturn 201 Created
Returning a body with 204 No ContentUse empty body
Mixing view controllers and REST APIs accidentallyUse @Controller and @RestController intentionally
Replacing all message converters in BootUse extendMessageConverters
Exposing technical error detailsReturn 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

AnnotationPurpose
@ControllerMVC controller, usually returns views
@RestControllerREST controller, returns response bodies
@RequestMappingGeneral request mapping
@GetMappingMaps HTTP GET
@PostMappingMaps HTTP POST
@PutMappingMaps HTTP PUT
@PatchMappingMaps HTTP PATCH
@DeleteMappingMaps HTTP DELETE
@ResponseBodyWrites return value to response body
@RequestBodyReads request body
@ResponseStatusSets fixed response status
@ControllerAdviceGlobal MVC advice
@RestControllerAdviceGlobal REST advice
@ExceptionHandlerHandles exceptions

Request Data Annotations

AnnotationSource
@PathVariableURI path
@RequestParamQuery string or form parameter
@RequestHeaderHTTP header
@CookieValueCookie
@RequestBodyHTTP request body
@ModelAttributeRequest parameters bound to object

REST Method Summary

MethodTypical OperationRequest Body?Response
GETRead resourceNo200 OK
POSTCreate resourceYes201 Created
PUTReplace resourceYes200 OK or 204 No Content
PATCHPartial updateYes200 OK or 204 No Content
DELETEDelete resourceUsually no204 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

NeedUse
URI path value@PathVariable
Query parameter@RequestParam
Header value@RequestHeader
Cookie value@CookieValue
JSON request body@RequestBody
Validate body@Valid @RequestBody
Return status and headersResponseEntity
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 ResponseEntity when status or headers matter.
  • Prefer @RestControllerAdvice for REST API errors.