Start here. This is the direct spoken answer to practice first.
Overview
The annotation should express where a value comes from and whether absence is valid.
I use @PathVariable for a value embedded in the route, @RequestParam for query or form parameters, @RequestHeader for headers, and @RequestBody for a body converted by an HttpMessageConverter. Simple values are converted to the declared Java type, while a JSON body is deserialized into one object. Required flags, defaults, or Optional express absence deliberately. A request has one consumable body, so I model related JSON fields in one request DTO.