Конвейер обработки запроса
В центре Spring MVC стоит DispatcherServlet — единый front controller, через который проходят все запросы. Он не обрабатывает запрос сам, а оркеструет: по URL находит обработчик через HandlerMapping, вызывает его через подходящий HandlerAdapter, а результат превращает в ответ.
Дальше развилка: для @RestController возвращённый объект сериализуется в тело ответа через HttpMessageConverter (обычно Jackson → JSON); для @Controller с именем представления подключается ViewResolver и рендерит шаблон. Понимание этого конвейера снимает вопрос «как Spring находит и вызывает мой метод».

@Controller против @RestController
@RestController = @Controller + @ResponseBody: возвращаемые объекты сериализуются прямо в тело ответа, без @ResponseBody на каждом методе. Это выбор для REST API.
Обычный @Controller по умолчанию трактует возвращённую строку как ИМЯ ПРЕДСТАВЛЕНИЯ (view) и ищет шаблон — частый источник путаницы у тех, кто ждёт JSON, а получает 404 по несуществующему шаблону.
Маппинг запросов
@RequestMapping задаёт базовый путь и общие атрибуты, а @GetMapping/@PostMapping/@PutMapping/@PatchMapping/@DeleteMapping — это его сокращения под конкретный HTTP-метод.
Маппинг можно сузить по типу содержимого: consumes (какой Content-Type принимает) и produces (какой отдаёт) — основа content negotiation.
@RestController
@RequestMapping("/users")
class UserController {
@GetMapping("/{id}")
User byId(@PathVariable long id) { /* ... */ }
}
Извлечение данных из запроса
Параметры метода связываются с частями запроса аннотациями: @PathVariable (часть пути /users/{id}), @RequestParam (query-параметр ?page=2), @RequestBody (тело запроса — десериализуется из JSON в объект), @RequestHeader (заголовок).
@RequestBody превращает JSON в объект через тот же HttpMessageConverter; @ModelAttribute собирает объект из параметров формы. Типы конвертируются автоматически (строка пути → long).
Контроль ответа
По умолчанию успешный метод возвращает 200 и тело-объект. Когда нужен явный контроль статуса и заголовков, возвращают ResponseEntity (например, 201 Created с заголовком Location) или ставят @ResponseStatus.
Это граница: бизнес-логику не стоит завязывать на ResponseEntity повсюду — обычно контроллер тонкий, а статус-коды и ошибки централизуют (см. урок про валидацию и обработку ошибок).
Как отвечать на собеседовании
Опишите конвейер DispatcherServlet → HandlerMapping → HandlerAdapter → контроллер → HttpMessageConverter/ViewResolver. Различите @RestController (тело через converter) и @Controller (имя view — частая ловушка). Назовите аннотации извлечения (@PathVariable/@RequestParam/@RequestBody) и контроль ответа через ResponseEntity.