Spring Boot: Неможливо отримати доступ до контролера REST на localhost (404)


105

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

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

POM:

<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...!";
   }

}

Я будую цей проект разом з Мейвен. Розпочали його як 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?


Як ви запускаєте додаток? Чи можете ви включити якісь журнали?
wjans

Спробував це окремо через Eclipse і за допомогою mvn spring-boot: run (як jar). Дивіться вище про журнали (відредаговано)
mchlfchr

З журналу запуску не схоже, що він знаходить ваш контролер, в якому пакеті знаходиться ваш клас контролера?
MattR

1
Це в окремому пакеті. Клас стартера з основним методом знаходиться в «застосуванні», поки контролер знаходиться в пакеті «контролер». Я бачив приклади (не ті, які були на spring.io), які також були структуровані таким чином.
mchlfchr

4
За замовчуванням Spring-boot сканує компоненти в тому ж пакеті або пакети "внизу" (той же префікс), що і ваш клас програми. В іншому випадку потрібно чітко просканувати їх, наприклад, використовуючи @ComponentScan
MattR

Відповіді:


198

Спробуйте додати наступне до класу InventoryApp

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

spring-boot буде перевіряти компоненти в упаковках нижче com.nice.application, тому, якщо ваш контролер є, com.nice.controllerвам потрібно сканувати його чітко.


У мене такі самі проблеми. Я намагаюся з componentscan але нічого :-( HIER моє запитання: stackoverflow.com/questions/33000931 / ...
emoleumassi

1
Зверніть увагу, що @SpringBootApplicationвключає@Configuration
krzakov

9
Здається, найпростіше помістити Програму в пакет «root», наприклад, «org.wever» та контролери, служби в підпакети.
insan-e

7
У мене така ж проблема, але перш ніж прийти до цього рішення, я знайшов його ... Більше. візьміть свій клас застосування весняного завантаження (у якому визначено основний метод) на один рівень до пакета контролера. тоді контролери будуть видимі для цього і будуть працювати
Tayab Hussain

1
Ви також можете використовувати "@ComponentScan (basePackages =" com.nice.controller ")". Компонентне сканування за замовчуванням починається на шляху, де є клас додатків, і сканувати також допоміжні пакети. У цьому випадку вам не потрібно використовувати анотацію @ComponentScan. Це робиться автоматично. Якщо у вас більше 1 контролера, можливо, їх також є в різних пакетах, ви можете ланцюжок. У цьому випадку важливо уникати конфліктів.
hariprasad

48

Додавання відповіді MattR в:

Як зазначено в тут , @SpringBootApplicationавтоматично вставляє необхідні анотації: @Configuration, @EnableAutoConfiguration, а також @ComponentScan; однак, @ComponentScanбуде шукати лише компоненти в тому ж пакеті, що і додаток, у цьому випадку ваш com.nice.application, тоді як ваш контролер проживає в com.nice.controller. Ось чому ви отримуєте 404, оскільки додаток не знайшов контролер у applicationпакеті.


5
Якщо це не зовсім зрозуміло вже з наведеного вище пояснення, клас із анотацією @SpringBootApplication повинен бути ВІДЗНАЧЕНО або на тому ж рівні в структурі вашого каталогу, як і те, що ви хочете знайти. Наприклад, у мене були com.app.configuration та com.app.controllers. Я помилково помістив свій клас Application в com.app.configuration, і все інше в com.app.configuration працювало нормально, але нічого в контролерах com.app. не завантажувалося. Я переніс свій клас Application в com.app, і боби в іншому місці знайшли, і все почало працювати. Початкова помилка для мене.
glaukommatos

2
Додавання @ComponentScan (basePackages = "com.base.package") вирішило це в моєму випадку
Shamli

Це справді допомагає.
Мадху Томі

12

Розробники SpringBoot рекомендують розміщувати ваш основний клас програми в кореневому пакеті над іншими класами. Використання кореневого пакету також дозволяє використовувати анотації @ComponentScan без необхідності вказувати атрибут basePackage . Детальна інформація Але переконайтеся, що існує спеціальний пакет root.


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"
}

1
Якщо ви не бачите інших читачів, @Controller->@RestController
Janac Meena

7

У мене виникла ця проблема, і вам потрібно буде виправити ваші пакунки. Якщо ви завантажили цей проект з http://start.spring.io/, у вас є основний клас у якомусь пакеті. Наприклад, якщо пакет основного класу є: "com.example", тоді ваш контролер повинен бути в пакеті: "com.example.controller". Сподіваюся, це допомагає.


6

Існує 2 способи подолання цього

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

    Приклад:

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

    Ви відпочиваєте в контролері з тією ж структурою пакета Приклад: package com.spring.boot.app.rest;

  2. Явно визначте Контролер у пакеті Bootup.

Спосіб 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;

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

Отже, якщо ви правильно змінили структури пакетів своїх пакетів проектів, то ваш додаток для весняного завантаження буде працювати правильно.


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

для мене я додавав у свій pom.xml Spring-web замість spring-boot-starter-web

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


0

Він також працює, якщо ми використовуємо наступне:

@SpringBootApplication(scanBasePackages = { "<class ItemInventoryController package >.*" })

0

Можливо, щось інше працює на порту 8080, і ви насправді підключаєтесь до нього помилково.

Однозначно перевірте це, особливо якщо у вас є докери, які пропонують інші сервіси, якими ви не керуєте, і пересилаєте порти цих служб.


0

Проблема полягає в структурі вашого пакета. Програма Spring Boot має специфічну структуру пакету, що дозволяє весняному контексту сканувати та завантажувати різні боби в його контексті.

У com.nice.application - це ваш основний клас, а в com.nice.controller - ваш клас контролерів.

Перемістіть пакет com.nice.controller у програму com.nice.application, щоб весна отримала доступ до ваших бобів.


-1

Ви можете додати всередину POM.

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-configuration-processor</artifactId>
    <version>XXXXXXXXX</version>
</dependency>

-2

Помістіть свій клас Springbootapplication у пакет root, наприклад, якщо ваша служба, контролер знаходиться у пакунку springBoot.xyz, то ваш основний клас повинен бути у пакунку springBoot, інакше він не буде сканувати нижче пакетів

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.