Вступление
В 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.