REST Controllers
Mapping requests
@RestController = @Controller + @ResponseBody: return values are serialized, not
resolved as view names.
Reading the request
| Annotation | Source | Example |
|---|---|---|
@PathVariable | URL segment | /books/7 |
@RequestParam | query string | ?page=2&size=20 |
@RequestBody | JSON body | POST payload |
@RequestHeader | header | Authorization |
@CookieValue | cookie | session id |
Records as DTOs
Keep web types separate from database entities — otherwise every column change is an API change.
Status codes and headers
Or declare it:
| Situation | Status |
|---|---|
| read ok | 200 |
| created | 201 |
| deleted, no body | 204 |
| invalid input | 400 |
| not authenticated / not allowed | 401 / 403 |
| unknown id | 404 |
| conflict, e.g. duplicate | 409 |
Content negotiation
Jackson 3 handles JSON. Java time types serialize as ISO-8601 by default.
CORS
Globally:
MVC or WebFlux?
| Spring MVC | Spring WebFlux | |
|---|---|---|
| model | one thread per request | event loop, reactive |
| return | Book, List<Book> | Mono<Book>, Flux<Book> |
| use when | the normal case | streaming, very high concurrency |
With virtual threads (spring.threads.virtual.enabled=true) blocking MVC code scales far
enough for most services — start there.
Tip
Return ResponseEntity only when you need to control status or headers. Otherwise return
the payload and keep the signature readable.
★ Exercises
- Build
/api/bookswith an in-memoryListand the five CRUD methods. - Return 201 with a
Locationheader on create. - Add
?author=filtering with@RequestParam. - Return 404 for an unknown id (
ResponseEntity.notFound().build()). - Add a second endpoint returning the same book as plain text.