Request Mapping
Request Mapping
In the previous lesson you learned that @RestController marks a class as the entry point for HTTP traffic. But a controller on its own does nothing — you need to tell Spring which HTTP method and URL path should trigger each handler method. That is what request mapping annotations do, and choosing them correctly is one of the most important design decisions you make when building a REST API.
The Four Core HTTP Verbs
REST maps CRUD operations onto four HTTP methods, each with a distinct semantic contract:
- GET — retrieve a resource; must be safe (no side effects) and idempotent.
- POST — create a new resource, or trigger an action; not idempotent.
- PUT — replace a resource entirely; idempotent (calling it twice gives the same result).
- DELETE — remove a resource; idempotent.
Spring provides a dedicated shortcut annotation for each one. The older, generic @RequestMapping still works and is useful when you need to share a base path across all methods in a controller, but for individual handlers the shortcuts are cleaner and more readable.
@GetMapping
Use @GetMapping for any operation that reads data without modifying server state. A well-designed GET handler can be cached, retried safely, and called repeatedly with no concern about duplicate side effects.
@RequestMapping is a prefix. When you place @RequestMapping("/api/products") on the class, every method-level annotation appends to it. @GetMapping("/{id}") resolves to GET /api/products/{id}. This avoids repeating the base path on every method.
@PostMapping
POST is the right verb when you are asking the server to create something new. The canonical pattern is: the client sends a JSON body with the resource data, the server creates the resource, and the response contains the newly created resource (or at minimum its ID and a 201 Created status).
The @RequestBody annotation tells Spring to deserialize the incoming JSON into a Java object using Jackson. You will go deeper into Jackson and ResponseEntity in later lessons; for now, note that POST should return 201 Created, not 200 OK.
@PutMapping
PUT replaces the target resource completely. If the client sends a partial object, the server should treat missing fields as intentional nulls (or the resource's empty state). If you want partial updates, use PATCH instead — but that is covered in the best-practices lesson.
PUT /resources/{id} to create a resource if it does not exist (upsert). This is valid REST but requires the client to supply the ID. It is a good fit when IDs are natural keys (e.g. a username). When IDs are server-generated (e.g. auto-increment database keys), POST-to-create is the standard pattern.
@DeleteMapping
DELETE removes the identified resource. A successful delete conventionally returns 204 No Content — the operation succeeded but there is no body to return.
Path Design — Practical Rules
The URL structure you choose is part of your API's public contract. Changing it later is a breaking change for every client. These rules save pain:
- Use nouns, not verbs. The HTTP method is the verb. Write
/api/products, not/api/getProductsor/api/createProduct. - Use plural nouns for collections.
/api/productsfor the collection,/api/products/{id}for a member. Mixing singular and plural confuses callers. - Reflect relationships in the path. If a review belongs to a product, the path
/api/products/{productId}/reviewsmakes the ownership explicit. - Keep paths lowercase with hyphens.
/api/product-categories, not/api/productCategoriesor/api/ProductCategories. URLs are case-sensitive on most servers, and camelCase looks out of place. - Do not version in the path yet. Versioning is lesson 9; adding
/v1/on day one without a strategy creates clutter.
Under the Hood: How Annotations Map to @RequestMapping
The shortcut annotations are thin wrappers. For example, @GetMapping("/path") is exactly equivalent to @RequestMapping(value = "/path", method = RequestMethod.GET). Knowing this matters when you need to set additional attributes like produces (content negotiation) or consumes — you can use the shortcut and add those attributes directly:
IllegalStateException: Ambiguous mapping at startup. This is a good thing — it is a compile-time (well, startup-time) contract violation, not a silent runtime bug. Fix it by differentiating paths, methods, or consumes/produces constraints.
Summary
@GetMapping, @PostMapping, @PutMapping, and @DeleteMapping pin your handler methods to specific HTTP verbs and paths. Combine them with a class-level @RequestMapping prefix to keep your controller clean. Design your paths around resource nouns, use plural names for collections, and reflect ownership in nested sub-paths. In the next lesson you will see how to extract dynamic segments from those paths using @PathVariable and @RequestParam.