Автор оригинала: Rayven Yor Esplanada.
Вступление
В Spring Boot класс controller отвечает за обработку входящих запросов REST API, подготовку модели и возврат представления, которое будет отображаться в качестве ответа.
Классы контроллеров в Spring аннотируются либо аннотацией @Controller
, либо аннотацией @RestController
. Эти классы контроллеров помечаются как обработчики запросов, чтобы Spring мог распознавать их как службу RESTful во время выполнения.
В этом уроке мы рассмотрим определение аннотаций @Controller
и @RestController
, их варианты использования и разницу между этими двумя аннотациями.
Если вы новичок в Spring Boot, вы также можете ознакомиться с нашим полным руководством по созданию API REST Spring Boot .
Рабочий процесс Spring Boot REST API
Прежде чем определить две аннотации, мы быстро рассмотрим рабочий процесс того, как Spring Boot обрабатывает запросы и процессы REST API и возвращает ответ:
Во-первых, запрос принимается DispatcherServlet
, который отвечает за обработку любых входящих URL-запросов и сопоставление их соответствующим обработчикам в виде методов контроллера. После выполнения метода контроллера ресурс затем обрабатывается как ответ, который может быть либо JSON, либо XML.
На приведенной выше диаграмме два процесса, заключенные в прямоугольник, являются процессами, фактически реализованными разработчиком. Остальные выполняются службами Spring, работающими в фоновом режиме, включая DispatcherServlet
.
Аннотация @Controller
Аннотация @Controller
является специализацией общего стереотипа @Компонента
аннотации, которая позволяет распознавать класс как компонент, управляемый Spring.
Аннотация @Controller
расширяет вариант использования @Компонента
и помечает аннотированный класс как бизнес-уровень или уровень представления. Когда будет сделан запрос, это сообщит DispatcherServlet
о включении класса контроллера в сканирование методов, отображаемых аннотацией @RequestMapping
.
Теперь мы объявим фактический контроллер для определения бизнес-логики и обработки всех запросов, связанных с моделью Дерево
.
Сначала отметьте класс аннотацией @Controller
вместе с @RequestMapping
и укажите путь к /api/дереву
:
@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
используется для автоматического введения зависимостей указанного типа в текущий компонент. В этом случае Хранилище дерева
компонент вводится как зависимость от Контроллера дерева
.
@GetMapping
– это ярлык для @RequestMapping(метод.GET)
, и используется для сопоставления HTTP GET
запросов с сопоставленными методами контроллера.
Мы применили аннотацию @ResponseBody
к уровню класса этого контроллера. Когда обработчики запросов возвращают данные обратно, такие как return repository.findById()
, ответ будет сериализован в JSON перед возвращением клиенту.
В качестве альтернативы вы могли бы вместо этого аннотировать каждый тип ответа аннотацией @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
вместо прямого аннотирования его @Компонентом
.
Если мы заменим аннотацию нашего контроллера на @RestController
, нам не нужно будет менять домен и уровень сохраняемости, поскольку они по-прежнему будут совместимы с этой аннотацией.
Git Essentials
Ознакомьтесь с этим практическим руководством по изучению Git, содержащим лучшие практики и принятые в отрасли стандарты. Прекратите гуглить команды Git и на самом деле изучите это!
Используя пример контроллера 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
, поскольку @RestController
применяет ее на уровне класса.
Если мы запустим это приложение, предположив, что у нас уже есть экземпляр Tree
, сохраненный в базе данных, с идентификатором 1, и нажмем localhost:8080/1
конечная точка, нас встретят:
{"species":"Salix babylonica","commonName":"Weeping willow", "age":"150"}
Вывод
По сути, @RestController
расширяет возможности как @Controller
, так и @ResponseBody
аннотации.
Помимо того факта, что @RestController
существует для того, чтобы контроллеры Spring были на одну строку короче, между этими двумя аннотациями нет никаких существенных различий.
Основная функция обеих аннотаций состоит в том, чтобы разрешить распознавание класса как компонента, управляемого Spring, и разрешить обработку HTTP-запросов с использованием REST API.