Вступление
В Spring Boot класс контроллера отвечает за обработку входящих запросов REST API, подготовку модели и возврат представления для отображения в качестве ответа.
Классы контроллеров в Spring аннотируются аннотацией @Controller или
@RestController . Они помечают классы контроллеров как обработчики
запросов, чтобы Spring мог распознать их как службу RESTful во время
выполнения.
В этом руководстве мы рассмотрим определение @Controller и
@RestController , их варианты использования и разницу между двумя
аннотациями.
Если вы новичок в Spring Boot, вы также можете ознакомиться с нашим полным руководством по созданию Spring Boot REST API .
Рабочий процесс Spring Boot REST API
Прежде чем определять две аннотации, мы быстро рассмотрим рабочий процесс того, как Spring Boot обрабатывает запросы и обработку REST API и возвращает ответ:

Сначала запрос получает DispatcherServlet , который отвечает за
обработку любых входящих запросов URI и сопоставление их с
соответствующими обработчиками в виде методов контроллера. После
выполнения метода контроллера ресурс обрабатывается как ответ, который
может быть либо JSON, либо XML.
На приведенной выше диаграмме два процесса, заключенные в прямоугольник,
являются процессами, фактически реализованными разработчиком. Остальные
выполняются службами Spring, работающими в фоновом режиме, включая
DispatcherServlet .
Аннотация @Controller
@Controller - это специализация универсальной стереотипной
@Component , которая позволяет распознавать класс как управляемый
Spring компонент.
@Controller расширяет возможности использования @Component и
отмечает аннотированный класс как бизнес-уровень или уровень
представления. Когда запрос сделан, это проинформирует
DispatcherServlet о включении класса контроллера в сканирование
методов, отображаемых аннотацией @RequestMapping
Теперь мы объявим фактический контроллер для определения бизнес-логики и
обработки всех запросов, связанных с Tree модели.
Сначала отметьте класс @Controller вместе с @RequestMapping и
укажите путь к /api/tree :
@Controller
@ResponseBody
@RequestMapping("/api/tree")
public class TreeController {
@Autowired
private TreeRepository repository;
@GetMapping("/{id}")
public Tree getTreeById(@PathVariable int id) {
return repository.findById(id);
}
@GetMapping
public Tree getTreeById(@RequestParam String name,
@RequestParam int age) {
return repository.findFirstByCommonNameIgnoreCaseAndAge(name, age);
}
}
@Autowired используется для автоматического внедрения зависимостей
указанного типа в текущий bean-компонент. В этом случае TreeRepository
компонент TreeRepository вводится как зависимость от TreeController .
@GetMapping - это ярлык для
@RequestMapping(method = RequestMethod.GET) , который используется для
сопоставления GET с сопоставленными методами контроллера.
Мы применили @ResponseBody к уровню класса этого контроллера. Когда
обработчики запросов возвращают данные обратно, например
return repository.findById() , ответ будет сериализован в JSON перед
возвратом клиенту.
В качестве альтернативы вы могли бы аннотировать каждый тип
@ResponseBody аннотацией @ResponseBody:
@GetMapping("/{id}")
public @ResponseBody Tree getTreeById(@PathVariable int id) {
return repository.findById(id);
}
Если мы запустим это приложение, предполагая, что у нас уже есть Tree
сохраненный в базе данных, с идентификатором 1, и попадем в конечную
точку localhost:8080/1
{"species":"Salix babylonica","commonName":"Weeping willow", "age":"150"}
Из-за @ResponseBody поля из извлеченного объекта сериализуются в JSON
и возвращаются клиенту, который его запросил.
Аннотация @RestController
@RestController в Spring по сути представляют собой просто комбинацию
@Controller и @ResponseBody . Эта аннотация была добавлена в Spring
4.0, чтобы удалить избыточность объявления @ResponseBody в вашем
контроллере.
Это на одну аннотацию меньше! Если вы также посмотрите на определение интерфейса двух аннотаций, чтобы увидеть разницу между ними:
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Controller
@ResponseBody
public @interface RestController {
//..
}
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Component
public @interface Controller {
//..
}
Интерфейс RestController аннотируется @Controller и @ResponseBody
вместо того, чтобы напрямую аннотировать его с помощью @Component .
Если мы заменим аннотацию нашего контроллера на @RestController , нам
не нужно будет изменять домен и уровень сохраняемости, поскольку они все
равно будут совместимы с этой аннотацией.
TreeController выше пример контроллера TreeController, давайте сравним
изменения, когда мы используем эту аннотацию:
@RestController
@RequestMapping("/api/tree")
public class TreeController {
@Autowired
private TreeRepository repository;
@GetMapping("/{id}")
public Tree getTreeById(@PathVariable int id) {
return repository.findById(id);
}
@GetMapping
public Tree getTreeById(@RequestParam String name,
@RequestParam int age) {
return repository.findFirstByCommonNameIgnoreCaseAndAge(name, age);
}
}
Теперь ко всем методам @ResponseBody аннотация @ResponseBody,
поскольку @RestController применяет ее на уровне класса.
Если мы запустим это приложение, предполагая, что у нас уже есть Tree
сохраненный в базе данных, с идентификатором 1, и попадем в конечную
точку localhost:8080/1
{"species":"Salix babylonica","commonName":"Weeping willow", "age":"150"}
Заключение
По сути, @RestController расширяет возможности аннотаций @Controller
и @ResponseBody
Помимо того факта, что @RestController существует для того, чтобы
контроллеры Spring были на одну строку короче, между двумя аннотациями
нет каких-либо серьезных различий.
Основная функция обеих аннотаций - позволить классу распознаваться как компонент, управляемый Spring, и разрешить обработку HTTP-запросов с использованием REST API.