В чем разница между @Controller и @RestController в Spring Framework?

«В чем разница между @Controller и @RestController в Spring Framework?» — вопрос из категории Spring, который задают на 23% собеседований Java Разработчик. Ниже — развёрнутый ответ с разбором ключевых моментов.

Ответ

Обе аннотации отмечают класс как компонент, обрабатывающий HTTP-запросы, но предназначены для разных архитектурных стилей.

@Controller (для MVC с представлениями)

  • Назначение: Часть паттерна Model-View-Controller (MVC). Ожидается, что метод вернёт имя представления (view), которое будет преобразовано в HTML (например, Thymeleaf, JSP).
  • Возвращаемое значение: По умолчанию — String (имя view) или объект ModelAndView.
  • Для API: Чтобы вернуть данные (JSON/XML), нужно дополнительно аннотировать метод @ResponseBody.

Пример @Controller:

@Controller
@RequestMapping("/web")
public class WebController {
    @GetMapping("/users")
    public String getUserPage(Model model) {
        model.addAttribute("users", userService.findAll());
        return "users-view"; // Возвращает имя шаблона (users-view.html)
    }

    @GetMapping("/api/users")
    @ResponseBody // Без этого вернётся строка "allUsers" как имя view
    public List<User> getUsersApi() {
        return userService.findAll(); // Возвращает JSON
    }
}

@RestController (для REST API)

  • Назначение: Специализация @Controller для создания RESTful веб-сервисов. Все методы по умолчанию возвращают данные, а не имена представлений.
  • Состав: Эквивалент @Controller + @ResponseBody на уровне всего класса.
  • Возвращаемое значение: Любой объект, который сериализуется (в JSON/XML) и записывается прямо в тело HTTP-ответа.

Пример @RestController:

@RestController // = @Controller + @ResponseBody на классе
@RequestMapping("/api")
public class UserApiController {
    @GetMapping("/users")
    public List<User> getAllUsers() {
        return userService.findAll(); // Автоматически конвертируется в JSON
    }

    @PostMapping("/users")
    public ResponseEntity<User> createUser(@RequestBody User user) {
        User saved = userService.save(user);
        return ResponseEntity.created(URI.create("/api/users/" + saved.getId()))
                             .body(saved);
    }
}
Итог: Критерий @Controller @RestController
Основная цель Генерация HTML-страниц (MVC) Создание REST API (JSON/XML)
Возврат данных Требует @ResponseBody на методе По умолчанию все методы с @ResponseBody
Типичный возврат Имя view (String), ModelAndView Объект, ResponseEntity, @ResponseBody
Использование Веб-приложения с UI Микросервисы, мобильные бэкенды