Весенняя загрузка, регистрирующая оставшийся контроллер, не работает без сопоставления запросов на уровне класса

Однако, несмотря на то, что мой служебный компонент отображается как зарегистрированный компонент в контексте Spring, его URL-адрес не регистрируется. По сути, чтобы зарегистрировать мой компонент, который имеет аннотацию @RequestMapping на уровне метода, мне нужно определить отображение запроса на уровне класса. И тогда контекст Spring может зарегистрировать обработчик URL-адреса.

моя структура каталогов выглядит так:

├── pom.xml
├── src
│   ├── main
│   │   ├── java
│   │   │   └── com
│   │   │       └── awesomecrypto
│   │   │           └── backend
│   │   │               ├── SpringBootApp.java
│   │   │               ├── entity
│   │   │               │   └── MarketData.java
│   │   │               ├── repository
│   │   │               │   └── MarketDataRepository.java
│   │   │               └── service
│   │   │                   └── MarketDataService.java
│   │   └── resources

SpringBootApp.java

package com.awesomecrypto.backend;

// import statements.

@SpringBootApplication
public class SpringBootApp {

    public static void main(String[] args) {
        ApplicationContext applicationContext = SpringApplication.run(SpringBootApp.class, args);

        for (String name: applicationContext.getBeanDefinitionNames()) {
            System.out.println(name);
        }
    }
}

MarketDataService

package com.awesomecrypto.backend.service;

// import statements here.

@Component
public class MarketDataService {

    @Autowired
    private MarketDataRepository marketDataRepository;

    @GetMapping("/marketData")
    @ResponseBody
    public String getMarketData() {
        return "foobar";
    }
}

Без @RequestMapping, определенного на уровне класса MarketDataService, для URL-адреса "/ marketData" нет зарегистрированных обработчиков URL-адресов.

2018-05-28 15:15:11.357  INFO 30618 --- [ost-startStop-1] o.a.c.c.C.[Tomcat].[localhost].[/]       : Initializing Spring embedded WebApplicationContext
2018-05-28 15:15:11.357  INFO 30618 --- [ost-startStop-1] o.s.web.context.ContextLoader            : Root WebApplicationContext: initialization completed in 1295 ms
2018-05-28 15:15:11.460  INFO 30618 --- [ost-startStop-1] o.s.b.w.servlet.ServletRegistrationBean  : Servlet dispatcherServlet mapped to [/]
2018-05-28 15:15:11.465  INFO 30618 --- [ost-startStop-1] o.s.b.w.servlet.FilterRegistrationBean   : Mapping filter: 'characterEncodingFilter' to: [/*]
2018-05-28 15:15:11.465  INFO 30618 --- [ost-startStop-1] o.s.b.w.servlet.FilterRegistrationBean   : Mapping filter: 'hiddenHttpMethodFilter' to: [/*]
2018-05-28 15:15:11.465  INFO 30618 --- [ost-startStop-1] o.s.b.w.servlet.FilterRegistrationBean   : Mapping filter: 'httpPutFormContentFilter' to: [/*]
2018-05-28 15:15:11.465  INFO 30618 --- [ost-startStop-1] o.s.b.w.servlet.FilterRegistrationBean   : Mapping filter: 'requestContextFilter' to: [/*]
2018-05-28 15:15:11.601  INFO 30618 --- [           main] o.s.w.s.handler.SimpleUrlHandlerMapping  : Mapped URL path [/**/favicon.ico] onto handler of type [class org.springframework.web.servlet.resource.ResourceHttpRequestHandler]
2018-05-28 15:15:11.813  INFO 30618 --- [           main] s.w.s.m.m.a.RequestMappingHandlerAdapter : Looking for @ControllerAdvice: org.springframework.boot.web.servlet.context.AnnotationConfigServletWebServerApplicationContext@6c65519: startup date [Mon May 28 15:15:10 PDT 2018]; root of context hierarchy
2018-05-28 15:15:11.915  INFO 30618 --- [           main] s.w.s.m.m.a.RequestMappingHandlerMapping : Mapped "{[/error]}" onto public org.springframework.http.ResponseEntity<java.util.Map<java.lang.String, java.lang.Object>> org.springframework.boot.autoconfigure.web.servlet.error.BasicErrorController.error(javax.servlet.http.HttpServletRequest)
2018-05-28 15:15:11.916  INFO 30618 --- [           main] s.w.s.m.m.a.RequestMappingHandlerMapping : Mapped "{[/error],produces=[text/html]}" onto public org.springframework.web.servlet.ModelAndView org.springframework.boot.autoconfigure.web.servlet.error.BasicErrorController.errorHtml(javax.servlet.http.HttpServletRequest,javax.servlet.http.HttpServletResponse)
2018-05-28 15:15:11.939  INFO 30618 --- [           main] o.s.w.s.handler.SimpleUrlHandlerMapping  : Mapped URL path [/webjars/**] onto handler of type [class org.springframework.web.servlet.resource.ResourceHttpRequestHandler]
2018-05-28 15:15:11.939  INFO 30618 --- [           main] o.s.w.s.handler.SimpleUrlHandlerMapping  : Mapped URL path [/**] onto handler of type [class org.springframework.web.servlet.resource.ResourceHttpRequestHandler]

С другой стороны, marketDataService регистрируется в весеннем контексте, что не имеет смысла. Вот соответствующие журналы getBeanDefinitionNames.

org.springframework.context.event.internalEventListenerFactory
springBootApp
org.springframework.boot.autoconfigure.internalCachingMetadataReaderFactory
marketDataRepository
marketDataService
org.springframework.boot.autoconfigure.AutoConfigurationPackages
org.springframework.boot.autoconfigure.context.PropertyPlaceholderAutoConfiguration
org.springframework.boot.autoconfigure.condition.BeanTypeRegistry

Теперь, если я добавлю @RequestMapping("/test") поверх MarketDataService, то Spring зарегистрирует обработчик URL-адресов.

2018-05-28 15:20:31.320  INFO 31536 --- [           main] s.w.s.m.m.a.RequestMappingHandlerMapping : Mapped "{[/test/marketData],methods=[GET]}" onto public java.lang.String com.awesomecrypto.backend.service.MarketDataService.getMarketData()

Я запускаю приложение с;

mvn clean package

mvn spring-boot:run

Все примеры в Интернете не упоминают об этом и похоже, что RequestMapping уровня класса не требуется, но я не мог этого сделать. Благодарю за вашу помощь. Спасибо!

Правильный способ - аннотировать ваш класс с помощью @RestController.

Indraneel Bende 29.05.2018 01:29

Вам также не нужен компонент. или аннотация ResponseBody

Indraneel Bende 29.05.2018 01:30
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
В компьютерном программировании биты играют важнейшую роль в представлении и манипулировании данными на двоичном уровне. Побитовые операции...
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Приходилось ли вам сталкиваться с требованиями, в которых вас могли попросить поднять тревогу или выдать ошибку, когда метод Java занимает больше...
Полный курс Java для разработчиков веб-сайтов и приложений
Полный курс Java для разработчиков веб-сайтов и приложений
Получите сертификат Java Web и Application Developer, используя наш курс.
1
2
3 666
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Вам не нужно RequestMapping на уровне класса. Измените свой код на этот, и он будет работать на вас.

 @RestController
 public class MarketDataService {

    @Autowired
    private MarketDataRepository marketDataRepository;

    @GetMapping("/marketData")
    public String getMarketData() {
     return "foobar";
    }
  }

Я бы посоветовал вам больше узнать об архитектуре Spring MVC.

https://docs.spring.io/spring/docs/current/spring-framework-reference/web.html#mvc

Также вы можете прочитать javaDocs для RequestMapping, RestController.

https://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/web/bind/annotation/RequestMapping.html

https://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/web/bind/annotation/RestController.html

Ваша первая ссылка - это документация из Spring 3.2.x, в которой еще не было аннотации @RestController, так как она была добавлена ​​в 4.0.

TwiN 29.05.2018 02:02

RestController - это не что иное, как Controller и ResponseBody вместе. Аннотация удобства,

Indraneel Bende 29.05.2018 02:24

Да, но если вы предложите ему прочитать статью, эта статья должна, по крайней мере, объяснить ответ, который вы ему даете. Поскольку @RestController не входит в первую статью, которую вы предложили ему прочитать, не означает ли это, что он не поймет ваш ответ? Последняя версия первой ссылки следующая: docs.spring.io/spring/docs/current/spring-framework-referenc‌ e /…

TwiN 29.05.2018 02:39

Конечно, я хотел, чтобы он разбирался в архитектуре Spring MVC.

Indraneel Bende 29.05.2018 02:49

Итак, он будет знать, как все работает за кулисами. И это улучшит его форму, когда в следующий раз у него возникнет проблема с Spring MVC.

Indraneel Bende 29.05.2018 02:50

Обновил свой ответ последней ссылкой.

Indraneel Bende 29.05.2018 02:54
Ответ принят как подходящий

Ваша аннотация @GetMapping игнорируется, потому что нет аннотации типа @Controller в верхней части вашего класса MarketDataService.

В вашем случае вы должны использовать @RestController (который сам аннотирован @Controller и @ResponseBody):

@RestController
public class MarketDataService {

    @Autowired
    private MarketDataRepository marketDataRepository;

    @GetMapping("/marketData")
    public String getMarketData() {
        return "foobar";
    }

}

Использование @RequestMapping в классе заключается в передаче заданного параметра, а также заданного параметра пути дочерним сопоставлениям в том же классе.

Например, добавление @RequestMapping("/api") над классом MarketDataService будет означать, что путь для запуска метода getMarketData() будет /api/marketData вместо /marketData.

Точно так же, если вы добавили @RequestMapping(value = "/api", produces = "application/json"), он передаст параметр produces = "application/json" в @GetMapping("/marketData").

Я вижу, что @RequestMapping часто используется в классе, когда контроллер используется для CRUD данного ресурса, например:

@RestController
@RequestMapping("/marketData")
public class MarketDataService {

    @Autowired
    private MarketDataRepository marketDataRepository;

    @PostMapping("")
    public String createMarketData() {
        // ...
    }

    @GetMapping("")
    public String getAllMarketData() {
        // ...
    }

    @GetMapping("/{id}")
    public String getMarketDataById(@PathVariable Long id) {
        // ...
    }

    @DeleteMapping("")
    public String deleteAllMarketData() {
        // ...
    }

    @DeleteMapping("/{id}")
    public String deleteMarketDataById(@PathVariable Long id) {
        // ...
    }

    // ...

}

Спасибо. На самом деле я знаю, что использование RequestMapping на уровне класса расширит путь URL-адреса до URL-адресов уровня метода, однако я не знал, что мне нужно использовать @Controller или @RestController для регистрации обработчиков уровня метода. Это устранило проблему. Хотя я ожидал, что Component должен работать, потому что аннотация @Controller расширяется от аннотации @Component. Кстати еще раз спасибо

quartaela 29.05.2018 02:05

Другие вопросы по теме