🌐 Request Binding in Spring MVC

When an HTTP request hits your controller, Spring must bind the incoming data β€” path, query, form, or JSON body β€” to your method parameters.

There are three main β€œdoors” for that data:

Layer Annotation Source Typical Example
Identity @PathVariable Path segment /users/{id}
Filters / form inputs @RequestParam Query string or form field /users?active=true&page=2
Payload @RequestBody Request body (JSON/XML) { "name": "Ana" }

🧠 Mental Model β€” β€œWhere does the data live?”

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚       HTTP REQUEST           β”‚
β”‚                              β”‚
β”‚  GET /users/42?active=true   β”‚
β”‚  Body: { "name": "Ana" }     β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
              β”‚
              β–Ό
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ Controller Method            β”‚
β”‚                              β”‚
β”‚ @PathVariable Long id        β”‚ ← /users/42
β”‚ @RequestParam Boolean active β”‚ ← ?active=true
β”‚ @RequestBody UserDto body    β”‚ ← JSON body
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

βš™οΈ Core Purposes

Intent Use Example
Identify a resource @PathVariable /users/{id}
Filter, sort, paginate @RequestParam /users?active=true&page=2
Create or update data @RequestBody POST /users with {...}

🧩 Engine Differences

Annotation Bound from Conversion Engine Typical Content-Type
@PathVariable URL template ConversionService text/plain (implicit)
@RequestParam Query/form field ConversionService application/x-www-form-urlencoded, multipart/form-data
@RequestBody Request body HttpMessageConverter (e.g., Jackson JSON) application/json, application/xml

βš–οΈ Comparison Summary

Dimension @PathVariable @RequestParam @RequestBody
Source URL segment Query string / form HTTP body
When used Identify which resource Filter or adjust request Send or receive structured data
Default scope Required Required (can default/optional) Required
Type conversion String β†’ simple type String β†’ simple type JSON/XML β†’ object
Cache key relevance Yes (different URL = different resource) Yes (different query = different resource) No (body not used in cache key)
Validation level Simple Simple Deep (object graph)
Good for REST paths Filters, toggles, pagination DTOs for create/update
Don’t use for JSON bodies Complex objects Filters or identifiers

πŸ” Real-World Mapping Example

POST /shops/7/orders?express=true
Body: { "item": "Book", "qty": 3 }
@PostMapping("/shops/{shopId}/orders")
public OrderDto createOrder(
    @PathVariable long shopId,           // /shops/7
    @RequestParam(defaultValue="false") boolean express, // ?express=true
    @RequestBody OrderCreateRequest body // { "item": "Book", "qty": 3 }
) { ... }

🧭 Folder Placement

cheatsheets/frameworks/spring/web/
└─ binding/
   β”œβ”€ overview.md          # ← this file
   β”œβ”€ path-variable.md
   β”œβ”€ request-param.md
   └─ request-body.md

In MkDocs navigation:

- Spring Web:
  - Binding (overview): cheatsheets/frameworks/spring/web/binding/overview.md
  - PathVariable: cheatsheets/frameworks/spring/web/binding/path-variable.md
  - RequestParam: cheatsheets/frameworks/spring/web/binding/request-param.md
  - RequestBody: cheatsheets/frameworks/spring/web/binding/request-body.md

πŸͺœ Next Layers

Once you master these three, your next frontier:

  • @ModelAttribute β€” group multiple @RequestParams into a validated object.
  • @ResponseBody β€” the reverse: converting your method return value to JSON/XML.
  • @MatrixVariable β€” niche but powerful for REST-like filtering in path segments.

Bottom line:

@PathVariable locates the thing, @RequestParam describes how to get it, @RequestBody tells what it is.

Use this trinity as your mental compass for every REST endpoint you design.