Spring Boot: нет доступа к контроллеру REST на локальном хосте (404)

105

Я пытаюсь адаптировать пример контроллера REST на веб-сайте Spring Boot. К сожалению, при попытке получить доступ к localhost:8080/itemURL-адресу возникает следующая ошибка .

{
  "timestamp": 1436442596410,
  "status": 404,
  "error": "Not Found",
  "message": "No message available",
  "path": "/item"
}

ПОМ:

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
   xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
   <modelVersion>4.0.0</modelVersion>
   <groupId>SpringBootTest</groupId>
   <artifactId>SpringBootTest</artifactId>
   <version>0.0.1-SNAPSHOT</version>
   <properties>
      <javaVersion>1.8</javaVersion>
      <mainClassPackage>com.nice.application</mainClassPackage>
      <mainClass>${mainClassPackage}.InventoryApp</mainClass>
   </properties>

   <build>
      <plugins>
         <plugin>
            <artifactId>maven-compiler-plugin</artifactId>
            <version>3.3</version>
            <configuration>
               <source>${javaVersion}</source>
               <target>${javaVersion}</target>
            </configuration>
         </plugin>

         <!-- Makes the Spring Boot app executable for a jar file. The additional configuration is needed for the cmd: mvn spring-boot:repackage 
            OR mvn spring-boot:run -->
         <plugin>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-maven-plugin</artifactId>

            <configuration>
               <mainClass>${mainClass}</mainClass>
               <layout>ZIP</layout>
            </configuration>
            <executions>
               <execution>
                  <goals>
                     <goal>repackage</goal>
                  </goals>
               </execution>
            </executions>
         </plugin>

         <!-- Create a jar with a manifest -->
         <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-jar-plugin</artifactId>
            <version>2.4</version>
            <configuration>
               <archive>
                  <manifest>
                     <mainClass>${mainClass}</mainClass>
                  </manifest>
               </archive>
            </configuration>
         </plugin>
      </plugins>
   </build>

   <dependencyManagement>
      <dependencies>
         <dependency>
            <!-- Import dependency management from Spring Boot. This replaces the usage of the Spring Boot parent POM file. -->
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-dependencies</artifactId>
            <version>1.2.5.RELEASE</version>
            <type>pom</type>
            <scope>import</scope>
         </dependency>

         <!-- more comfortable usage of several features when developing in an IDE. Developer tools are automatically disabled when 
            running a fully packaged application. If your application is launched using java -jar or if its started using a special classloader, 
            then it is considered a 'production application'. Applications that use spring-boot-devtools will automatically restart whenever files 
            on the classpath change. -->
         <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-devtools</artifactId>
         </dependency>
      </dependencies>
   </dependencyManagement>

   <dependencies>
      <dependency>
         <groupId>org.springframework.boot</groupId>
         <artifactId>spring-boot-starter-web</artifactId>
      </dependency>

      <dependency>
         <groupId>org.springframework.boot</groupId>
         <artifactId>spring-boot-starter-test</artifactId>
         <scope>test</scope>
      </dependency>

      <dependency>
         <groupId>com.google.guava</groupId>
         <artifactId>guava</artifactId>
         <version>15.0</version>
      </dependency>
   </dependencies>
</project>

Стартовое приложение:

package com.nice.application;
@SpringBootApplication // same as @Configuration @EnableAutoConfiguration @ComponentScan
public class InventoryApp {
   public static void main( String[] args ) {
      SpringApplication.run( InventoryApp.class, args );
   }
}

REST-контроллер:

package com.nice.controller; 
@RestController // shorthand for @Controller and @ResponseBody rolled together
public class ItemInventoryController {
   public ItemInventoryController() {
   }

   @RequestMapping( "/item" )
   public String getStockItem() {
      return "It's working...!";
   }

}

Я создаю этот проект с Maven. Запустил его как jar (spring-boot: run), а также внутри IDE (Eclipse).

Журнал консоли:

2015-07-09 14:21:52.132  INFO 1204 --- [           main] c.b.i.p.s.e.i.a.InventoryApp          : Starting InventoryApp on 101010002016M with PID 1204 (C:\eclipse_workspace\SpringBootTest\target\classes started by MFE in C:\eclipse_workspace\SpringBootTest)
2015-07-09 14:21:52.165  INFO 1204 --- [           main] ationConfigEmbeddedWebApplicationContext : Refreshing org.springframework.boot.context.embedded.AnnotationConfigEmbeddedWebApplicationContext@7a3d45bd: startup date [Thu Jul 09 14:21:52 CEST 2015]; root of context hierarchy
2015-07-09 14:21:52.661  INFO 1204 --- [           main] o.s.b.f.s.DefaultListableBeanFactory     : Overriding bean definition for bean 'beanNameViewResolver': replacing [Root bean: class [null]; scope=; abstract=false; lazyInit=false; autowireMode=3; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=org.springframework.boot.autoconfigure.web.ErrorMvcAutoConfiguration$WhitelabelErrorViewConfiguration; factoryMethodName=beanNameViewResolver; initMethodName=null; destroyMethodName=(inferred); defined in class path resource [org/springframework/boot/autoconfigure/web/ErrorMvcAutoConfiguration$WhitelabelErrorViewConfiguration.class]] with [Root bean: class [null]; scope=; abstract=false; lazyInit=false; autowireMode=3; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=org.springframework.boot.autoconfigure.web.WebMvcAutoConfiguration$WebMvcAutoConfigurationAdapter; factoryMethodName=beanNameViewResolver; initMethodName=null; destroyMethodName=(inferred); defined in class path resource [org/springframework/boot/autoconfigure/web/WebMvcAutoConfiguration$WebMvcAutoConfigurationAdapter.class]]
2015-07-09 14:21:53.430  INFO 1204 --- [           main] s.b.c.e.t.TomcatEmbeddedServletContainer : Tomcat initialized with port(s): 8080 (http)
2015-07-09 14:21:53.624  INFO 1204 --- [           main] o.apache.catalina.core.StandardService   : Starting service Tomcat
2015-07-09 14:21:53.625  INFO 1204 --- [           main] org.apache.catalina.core.StandardEngine  : Starting Servlet Engine: Apache Tomcat/8.0.23
2015-07-09 14:21:53.731  INFO 1204 --- [ost-startStop-1] o.a.c.c.C.[Tomcat].[localhost].[/]       : Initializing Spring embedded WebApplicationContext
2015-07-09 14:21:53.731  INFO 1204 --- [ost-startStop-1] o.s.web.context.ContextLoader            : Root WebApplicationContext: initialization completed in 1569 ms
2015-07-09 14:21:54.281  INFO 1204 --- [ost-startStop-1] o.s.b.c.e.ServletRegistrationBean        : Mapping servlet: 'dispatcherServlet' to [/]
2015-07-09 14:21:54.285  INFO 1204 --- [ost-startStop-1] o.s.b.c.embedded.FilterRegistrationBean  : Mapping filter: 'characterEncodingFilter' to: [/*]
2015-07-09 14:21:54.285  INFO 1204 --- [ost-startStop-1] o.s.b.c.embedded.FilterRegistrationBean  : Mapping filter: 'hiddenHttpMethodFilter' to: [/*]
2015-07-09 14:21:54.508  INFO 1204 --- [           main] s.w.s.m.m.a.RequestMappingHandlerAdapter : Looking for @ControllerAdvice: org.springframework.boot.context.embedded.AnnotationConfigEmbeddedWebApplicationContext@7a3d45bd: startup date [Thu Jul 09 14:21:52 CEST 2015]; root of context hierarchy
2015-07-09 14:21:54.573  INFO 1204 --- [           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.BasicErrorController.error(javax.servlet.http.HttpServletRequest)
2015-07-09 14:21:54.573  INFO 1204 --- [           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.BasicErrorController.errorHtml(javax.servlet.http.HttpServletRequest)
2015-07-09 14:21:54.594  INFO 1204 --- [           main] o.s.w.s.handler.SimpleUrlHandlerMapping  : Mapped URL path [/webjars/**] onto handler of type [class org.springframework.web.servlet.resource.ResourceHttpRequestHandler]
2015-07-09 14:21:54.594  INFO 1204 --- [           main] o.s.w.s.handler.SimpleUrlHandlerMapping  : Mapped URL path [/**] onto handler of type [class org.springframework.web.servlet.resource.ResourceHttpRequestHandler]
2015-07-09 14:21:54.633  INFO 1204 --- [           main] o.s.w.s.handler.SimpleUrlHandlerMapping  : Mapped URL path [/**/favicon.ico] onto handler of type [class org.springframework.web.servlet.resource.ResourceHttpRequestHandler]
2015-07-09 14:21:54.710  INFO 1204 --- [           main] o.s.j.e.a.AnnotationMBeanExporter        : Registering beans for JMX exposure on startup
2015-07-09 14:21:54.793  INFO 1204 --- [           main] s.b.c.e.t.TomcatEmbeddedServletContainer : Tomcat started on port(s): 8080 (http)
2015-07-09 14:21:54.795  INFO 1204 --- [           main] c.b.i.p.s.e.i.a.InventoryApp          : Started InventoryApp in 2.885 seconds (JVM running for 3.227)
2015-07-09 14:22:10.911  INFO 1204 --- [nio-8080-exec-1] o.a.c.c.C.[Tomcat].[localhost].[/]       : Initializing Spring FrameworkServlet 'dispatcherServlet'
2015-07-09 14:22:10.911  INFO 1204 --- [nio-8080-exec-1] o.s.web.servlet.DispatcherServlet        : FrameworkServlet 'dispatcherServlet': initialization started
2015-07-09 14:22:10.926  INFO 1204 --- [nio-8080-exec-1] o.s.web.servlet.DispatcherServlet        : FrameworkServlet 'dispatcherServlet': initialization completed in 15 ms

Что я пробовал до сих пор:

  • Доступ к URL-адресу с именем приложения (InventoryApp)
  • Поставьте другой @RequestMapping("/")на уровне классаItemInventoryController

Насколько я понял, мне не понадобится контекст приложения при использовании Spring Boot. Я прав?

Что еще я могу сделать, чтобы получить доступ к методу через URL?

mchlfchr
источник
Как вы запускаете приложение? Можете ли вы включить журналы?
wjans 09
Пробовал отдельно через Eclipse и с mvn spring-boot: run (как jar). Журналы см. Выше (отредактировано)
mchlfchr 09
Из журнала запуска не похоже, что он находит ваш контроллер, в каком пакете находится ваш класс контроллера?
MattR 09
1
Он в отдельной упаковке. Стартовый класс с основным методом находится в «приложении», а контроллер - в пакете «контроллер». Я видел примеры (не те, что на spring.io), которые также были структурированы таким образом.
mchlfchr 09
4
По умолчанию spring-boot будет сканировать компоненты в том же пакете или пакеты «ниже» (тот же префикс), что и ваш класс приложения. В противном случае вам нужно явно сканировать их, например, используя @ComponentScan
MattR

Ответы:

199

Попробуйте добавить следующее в свой класс InventoryApp

@SpringBootApplication
@ComponentScan(basePackageClasses = ItemInventoryController.class)
public class InventoryApp {
...

Spring-boot будет сканировать компоненты в пакетах ниже com.nice.application, поэтому, если ваш контроллер включен, com.nice.controllerвам нужно сканировать его явно.

MattR
источник
У меня такие же проблемы. Я пробую использовать компонентыcan, но ничего :-( Вот мой вопрос: stackoverflow.com/questions/33000931/…
emoleumassi
1
обратите внимание, что @SpringBootApplicationвключает@Configuration
krzakov
9
Кажется, проще всего поместить приложение в «корневой» пакет, например, в «org.whatever», а контроллеры и службы - в подпакеты.
insan-e
7
У меня та же проблема, но, прежде чем я пришел к этому решению, я нашел ее ... Более того. возьмите свой класс приложения весенней загрузки (в котором определен основной метод) на один уровень до пакета контроллера .. тогда контроллеры будут видны для этого и будут работать
Тайаб Хуссейн
1
Вы также можете использовать '@ComponentScan (basePackages = "com.nice.controller")'. Сканирование компонентов по умолчанию начинается с пути, где находится класс приложения, а также сканирование дополнительных пакетов. В этом случае вам не нужно использовать аннотацию @ComponentScan. Это происходит автоматически. Если у вас более 1 контроллера, их можно также разместить в разных пакетах, вы можете объединить их в цепочку. В этом случае важно избегать конфликтов.
hariprasad
48

Добавление ответа MattR в:

Как указано в здесь , @SpringBootApplicationавтоматически вставляет необходимые аннотации: @Configuration, @EnableAutoConfiguration, а также @ComponentScan; однако он @ComponentScanбудет искать только компоненты в том же пакете, что и приложение, в данном случае ваш com.nice.application, тогда как ваш контроллер находится в com.nice.controller. Вот почему вы получаете 404, потому что приложение не нашло контроллер в applicationпакете.

Cipley
источник
5
В случае, если это не совсем ясно из приведенного выше объяснения, класс с аннотацией @SpringBootApplication должен находиться НАД или на том же уровне в вашей структуре каталогов, что и вещи, которые вы хотите найти. Например, у меня были com.app.configuration и com.app.controllers. Я по ошибке поместил свой класс Application в com.app.configuration, и все остальное в com.app.configuration работало нормально, но ничего в com.app.controllers не загружалось. Я переместил свой класс Application в com.app, и bean-компоненты в другом месте были найдены, и все начало работать. Ошибка новичка для меня.
glaukommatos 08
2
Добавление @ComponentScan (basePackages = "com.base.package") решило эту проблему в моем случае
Шамли
Это действительно помогает.
Мадху Томи
12

Разработчики SpringBoot рекомендуют размещать основной класс вашего приложения в корневом пакете над другими классами. Использование корневого пакета также позволяет использовать аннотацию @ComponentScan без необходимости указывать атрибут basePackage . Подробная информация Но убедитесь, что пользовательский корневой пакет существует.

Торина
источник
10

Тот же ответ 404, который я получил после выполнения службы с приведенным ниже кодом

@Controller
@RequestMapping("/duecreate/v1.0")
public class DueCreateController {

}

Отклик:

{
"timestamp": 1529692263422,
"status": 404,
"error": "Not Found",
"message": "No message available",
"path": "/duecreate/v1.0/status"
}

после изменения его на код ниже я получил правильный ответ

@RestController
@RequestMapping("/duecreate/v1.0")
public class DueCreateController {

}

Отклик:

{
"batchId": "DUE1529673844630",
"batchType": null,
"executionDate": null,
"status": "OPEN"
}
Махендер Амбала
источник
2
Если другие читатели этого не видят, @Controller->@RestController
Janac Meena
7

У меня была эта проблема, и вам нужно исправить свои пакеты. Если вы загрузили этот проект с http://start.spring.io/, значит, у вас есть основной класс в каком-то пакете. Например, если пакет для основного класса: «com.example», тогда и ваш контроллер должен быть в пакете: «com.example.controller». Надеюсь это поможет.

f.trajkovski
источник
6

Есть 2 способа преодолеть это

  1. Поместите загрузочное приложение в начало структуры пакета и поместите в него весь контроллер.

    Пример :

    пакет com.spring.boot.app; - Вы загружаете приложение (т.е. основной метод -SpringApplication.run (App.class, args);)

    Вы оставите контроллер с той же структурой пакета. Пример: package com.spring.boot.app.rest;

  2. Явно определите контроллер в загрузочном пакете.

Метод 1 чище.

Мохаммед Сарфараз
источник
1
пружинный загрузочный ненавидит класс приложения находится под какой - то пакет, кроме базы package..if базового пакета org.someapp и если мы ставим под org.someapp.app это бомбы ..: - /
Priyank Thakkar
3

Вам необходимо изменить класс Starter-Application, как показано ниже.

@SpringBootApplication

@EnableAutoConfiguration

@ComponentScan(basePackages="com.nice.application")

@EnableJpaRepositories("com.spring.app.repository")

public class InventoryApp extends SpringBootServletInitializer {..........

И обновите структуру пакетов Controller, Service и Repository, как я упоминал ниже.

Пример: REST-контроллер

package com.nice.controller; -> Он должен быть изменен как
package com.nice.application.controller;

Вам необходимо соблюдать правильную структуру пакетов для всех пакетов, которые находятся в потоке Spring Boot MVC.

Итак, если вы правильно измените структуру пакетов вашего проекта, ваше приложение для загрузки Spring будет работать правильно.

Анжан
источник
3
EnableAutoConfiguration включен в @SpringBootApplication, поэтому добавлять его бесполезно.
Sofiane
1

Заменить @RequestMapping( "/item" )на @GetMapping(value="/item", produces=MediaType.APPLICATION_JSON_VALUE).

Может, это кому-нибудь поможет.

Игорь Хомяк
источник
1
это помогло мне понять , что я написал , nameа не valueв @GetMapping.
vortex.alex
0

У меня была точно такая же ошибка, я не давал базовый пакет. Предоставив правильный базовый пакет, переделал его.

package com.ymc.backend.ymcbe;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.ComponentScan;

@SpringBootApplication
@ComponentScan(basePackages="com.ymc.backend")
public class YmcbeApplication {

    public static void main(String[] args) {
        SpringApplication.run(YmcbeApplication.class, args);
    }

}

Примечание: не включая .controller @ComponentScan (basePackages = "com.ymc.backend.controller"), потому что у меня есть много других классов компонентов, которые мой проект не сканирует, если я просто даю .controller

Вот мой образец контроллера:

package com.ymc.backend.controller;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.CrossOrigin;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;


@RestController
@CrossOrigin
@RequestMapping(value = "/user")
public class UserController {

    @PostMapping("/sendOTP")
    public String sendOTP() {
        return "OTP sent";
    };


}
Набин Кумар Хативада
источник
0

Иногда пружинный ботинок ведет себя странно. Я указал ниже в классе приложения, и он работает:

@ComponentScan("com.seic.deliveryautomation.controller")
Любовь Кумара
источник
0

У меня проблема 404 из-за чувствительности к регистру URL .

Например, @RequestMapping(value = "/api/getEmployeeData",method = RequestMethod.GET)к нему можно получить доступ с помощью http://www.example.com/api/getEmployeeData. Если мы используем http://www.example.com/api/getemployeedata, то получим ошибку 404.

Примечание: http://www.example.comтолько для справки, о которой я упоминал выше. Это должно быть ваше доменное имя, на котором вы разместили свое приложение.

После долгой борьбы и применения всех остальных ответов в этом посте я понял, что проблема только в этом URL-адресе. Это может быть глупая проблема. Но это стоило мне 2 часа. Так что я надеюсь, что это кому-то поможет.

Махендран Саккарай
источник
0

для меня я добавлял spring-web вместо spring-boot-starter-web в свой pom.xml

когда я заменяю его с spring-web на spring-boot-starter-web, все сопоставления отображаются в журнале консоли.

Сакиров
источник
0

Это также работает, если мы используем следующее:

@SpringBootApplication(scanBasePackages = { "<class ItemInventoryController package >.*" })
Муралидхар
источник
0

Возможно, на порту 8080 работает что-то еще, и вы на самом деле подключаетесь к нему по ошибке.

Обязательно проверьте это, особенно если у вас есть докеры, которые вызывают другие службы, которые вы не контролируете, и перенаправляют эти службы.

Брэд Паркс
источник
0

Проблема в структуре вашего пакета. Приложение Spring Boot Application имеет особую структуру пакета, позволяющую контексту Spring сканировать и загружать различные bean-компоненты в своем контексте.

В com.nice.application находится ваш основной класс, а в com.nice.controller у вас есть классы контроллера.

Переместите пакет com.nice.controller в com.nice.application, чтобы Spring мог получить доступ к вашим beans.

Нареш Бхадке
источник
-1

Вы можете добавить внутрь POM.

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-configuration-processor</artifactId>
    <version>XXXXXXXXX</version>
</dependency>
Cemahi
источник
-2

Поместите свой класс springbootapplication в корневой пакет, например, если ваша служба, контроллер находится в пакете springBoot.xyz, тогда ваш основной класс должен быть в пакете springBoot, иначе он не будет сканировать следующие пакеты

ПГС
источник