Небольшая разница между @RestController и @Component - PullRequest
3 голосов
/ 13 октября 2019

Хотя на каждой странице в интернете написано, что @RestController - это спецификация @ Component. Я не знаю, связано ли это с DispatcherServlet. Но когда я пытаюсь выполнить приведенный ниже код, переключаясь между @RestController и @Component, я не вижу того же поведения:

Сначала я попробовал с @RestController:

@RestComponent
public class TestController {
    @RequestMapping(value="/testController", method=RequestMethod.POST,consumes=MediaType.APPLICATION_JSON_VALUE)
    public void testController() {
        System.out.println("Hello");
    }

}

Я получил ниже вывод вКонсоль:

Привет

Во-вторых, я попытался с @Component + @ResponseBody:

@Component
@ResponseBody
public class TestController {
    @RequestMapping(value="/testController", method=RequestMethod.POST,consumes=MediaType.APPLICATION_JSON_VALUE)
    public void testController() {
        System.out.println("Hello");
    }
}

Я получил ошибку на почтальоне:

{
    "timestamp": 1570998345860,
    "status": 405,
    "error": "Method Not Allowed",
    "message": "Request method 'POST' not supported",
    "path": "/testController"
}

Если обе аннотации одинаковы, то почему есть разница в выводе ??

Ниже приведен исходный код @RestController & @Controller, который показывает, что @RestController & @Controller являютсяспецификация @Component:

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Controller
@ResponseBody
public @interface RestController {

}


@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Component
public @interface Controller {
}

Возможно, это должно быть связано с DispatcherServlet. Возможно, что сервлет-диспетчер проверяет только URL-адреса в аннотированных классах @RestController.

Ответы [ 4 ]

1 голос
/ 13 октября 2019

То, что @RestController является @Component, не означает, что вы можете достичь той же функциональности, переключившись на более широкую @Component. Даже с добавлением @ResponseBody вы не получите эквивалентную функциональность (что выражается в методе запроса POST, который не поддерживается).

Замените @Component на @Controller, поскольку @RestController имеет те же функции, что и @Controller + @ResponseBody. Вы также можете видеть это в метааннотациях @RestController, вы видите, что это мета-аннотированы @Controller вместо просто @Component. В свою очередь, @Controller мета-аннотируется с @Component.

0 голосов
/ 14 октября 2019

@ Controller - пользователь в традиционном контроллере, и аннотация @RestController была введена для упрощения создания веб-сервисов RESTful. Это удобная аннотация, которая объединяет @Controller и @ ResponseBody

@ Аннотация контроллера - это просто специализированный класс @Component, позволяющий автоматически определять классы реализации при сканировании пути к классам.

@ Controller обычно используется в сочетании с аннотацией @RequestMapping, используемой в методах обработки запросов.

Метод обработки запросов аннотируется @ResponseBody. Эта аннотация позволяет автоматически сериализовать возвращаемый объект в HttpResponse.

@ RestController - это специализированная версия контроллера. Он включает аннотации @Controller и @ResponseBody и, как следствие, упрощает реализацию контроллера.

Контроллер аннотируется аннотацией @RestController, поэтому @ResponseBody не требуется.

Каждый метод обработки запросов класса контроллера автоматически сериализует возвращаемые объекты в HttpResponse.
Подробнее см. Здесь: https://www.baeldung.com/spring-controller-vs-restcontroller

0 голосов
/ 14 октября 2019

@Controller, @RestController, @Service и т. Д. - все аннотации, мета-аннотированные с аннотацией @Component. Все эти аннотации по сути являются специализациями аннотации @Component для конкретных случаев использования. Аннотация @Component обычно используется для регистрации bean-компонента Spring.

Аннотация @Controller, даже несмотря на то, что она внутренне аннотирована @Component, обеспечивает в целом другую функциональность. При аннотировании класса этой аннотацией мы, по сути, сообщаем Spring сканировать этот класс для аннотации @RequestMappingзарегистрировать бины для отображения запросов. Этого не происходит, когда вы просто используете аннотацию @Component.

Когда приложение Spring запускается, DispatcherServlet включит RequestMappingHandlerMapping RequestMappingHandlerAdapter (это отображение обработчика, которое ищет @RequestMapping аннотаций на @Controller с). Поэтому, когда запрос достигает сервлета диспетчера, он передает его RequestMappingHandlerMapping, который разрешает uri в bean-компонент метода контроллера. Для получения дополнительной информации читайте: DispatcherServlet, Обновлен Doc Spring 5.x HandlerMapping

Примечание. В более старых версиях пружины DefaultAnnotationHandlerMapping включается для этого весной.

Итак, в итоге:

  • @Component - это общий стереотип для любого компонента или компонента, управляемого Spring.
  • @Repository - это стереотип для уровня персистентности.
  • @Service - это стереотип дляуровень обслуживания.
  • @Controller - это стереотип для уровня представления (spring-MVC).

Spring [Doc] [4] .

Аннотация @Controller указывает на то, что определенный класс выполняет роль контроллера.

Основное назначение аннотации @Controller - выступать в качестве стереотипа для аннотированного класса. с указанием своей роли. Диспетчер будет сканировать такие аннотированные классы для сопоставленных методов, обнаруживая аннотации @RequestMapping (см. Следующий раздел).

Аннотированные компоненты контроллера могут быть определены явно, используя стандартное определение bean-компонента Spring в контексте диспетчера. Однако стереотип @Controller также допускает автоопределение, что согласуется с общей поддержкой Spring 2.5 для определения классов компонентов в classpath и автоматической регистрации определений bean-компонентов для них.

Аналогичный пост: В чем разница между аннотациями @Component, @Repository и @Service в Spring?

0 голосов
/ 14 октября 2019

Вы не должны получать такое же поведение, потому что @Component является более общим. Он регистрирует ваш класс только как Spring Managed Bean. Однако @RestController не только регистрирует ваш класс как управляемый компонент, но и регистрирует его как точку входа для HTTP-вызовов на указанный URL-путь. То же самое касается других аннотаций, относящихся к слою, таких как @Repository, @Configuration и т. Д.

...