Spring Boot: Zugriff auf REST-Controller auf localhost nicht möglich (404)

104

Ich versuche, das REST-Controller-Beispiel auf der Spring Boot-Website anzupassen. Leider habe ich den folgenden Fehler erhalten, wenn ich versuche, auf die localhost:8080/itemURL zuzugreifen .

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

Starter-Anwendung:

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-Controller:

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

}

Ich baue dieses Projekt mit Maven. Startete es als jar (spring-boot: run) und auch innerhalb der IDE (Eclipse).

Konsolenprotokoll:

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

Was ich bisher versucht habe:

  • Zugriff auf die URL mit dem Anwendungsnamen (InventoryApp)
  • Setzen Sie eine andere @RequestMapping("/")auf Klassenebene derItemInventoryController

Soweit ich verstanden habe, benötige ich bei Verwendung von Spring Boot keinen Anwendungskontext. Habe ich recht?

Was kann ich noch tun, um über eine URL auf die Methode zuzugreifen?

mchlfchr
quelle
Wie führen Sie die Anwendung aus? Können Sie vielleicht einige Protokolle hinzufügen?
Wjans
Versuchte es separat über Eclipse und mit mvn spring-boot: run (als jar). Siehe oben für Protokolle (bearbeitet)
mchlfchr
Aus dem Startprotokoll geht nicht hervor, dass es Ihren Controller findet. In welchem ​​Paket befindet sich Ihre Controller-Klasse?
MattR
1
Es ist in einem separaten Paket. Die Starterklasse mit der Hauptmethode befindet sich in "application", während sich der Controller im Paket "controller" befindet. Ich habe Beispiele gesehen (nicht die auf spring.io), die ebenfalls so strukturiert waren.
mchlfchr
4
Standardmäßig sucht Spring-Boot nach Komponenten im selben Paket oder nach Paketen "unten" (dasselbe Präfix) wie Ihre Anwendungsklasse. Andernfalls müssen Sie explizit nach ihnen suchen, z. B. mit @ComponentScan
MattR

Antworten:

196

Fügen Sie Ihrer InventoryApp-Klasse Folgendes hinzu

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

spring-boot sucht in den folgenden Paketen nach Komponenten. com.nice.applicationWenn sich Ihr Controller in befindet com.nice.controller, müssen Sie explizit danach suchen.

MattR
quelle
Ich habe die gleichen Probleme. Ich versuche mit dem Komponentenscan aber nichts :-( Hier meine Frage: stackoverflow.com/questions/33000931/…
emoleumassi
1
Bitte beachten Sie, dass @SpringBootApplicationenthält@Configuration
krzakov
9
Es scheint am einfachsten zu sein, die Anwendung in das "root" -Paket zu setzen, z. B. "org.whatever" und die Controller, Dienste in Unterpaketen.
Wahnsinn
7
Ich habe das gleiche Problem, aber bevor ich zu dieser Lösung kam, fand ich es ... Mehr vorbei. Nehmen Sie Ihre Spring Boot-Anwendungsklasse (in der die Hauptmethode definiert ist) eine Ebene bis zum Controller-Paket. Dann sind die Controller für diese sichtbar und funktionieren
Tayab Hussain,
1
Sie können auch '@ComponentScan (basePackages = "com.nice.controller")' verwenden. Der Standard-Scan der Komponente beginnt im Pfad, in dem sich die App-Klasse befindet, und scannt auch Nebenpakete. In diesem Fall müssen Sie die Annotation @ComponentScan nicht verwenden. Dies geschieht automatisch. Wenn Sie mehr als einen Controller haben, ist es möglich, diese auch in verschiedenen Paketen zu haben. Sie können sie verketten. In diesem Fall ist es wichtig, Konflikte zu vermeiden.
Hariprasad
46

Zusätzlich zu MattR Antwort:

Wie in angegeben hier , @SpringBootApplicationfügt automatisch die benötigten Anmerkungen: @Configuration, @EnableAutoConfigurationund auch @ComponentScan; Es wird jedoch @ComponentScannur nach den Komponenten im selben Paket wie die App gesucht, in diesem Fall nach Ihren com.nice.application, während sich Ihr Controller in befindet com.nice.controller. Deshalb erhalten Sie 404, weil die App den Controller nicht im applicationPaket gefunden hat.

Cipley
quelle
5
Falls dies aus der obigen Erläuterung noch nicht vollständig hervorgeht, muss sich die Klasse mit der Annotation @SpringBootApplication OBEN oder auf derselben Ebene in Ihrer Verzeichnisstruktur befinden wie die Dinge, die Sie finden möchten. Zum Beispiel hatte ich com.app.configuration und com.app.controllers. Ich habe fälschlicherweise meine Anwendungsklasse in com.app.configuration eingefügt, und alles andere in com.app.configuration hat einwandfrei funktioniert, aber nichts in com.app.controllers wurde geladen. Ich habe meine Anwendungsklasse in com.app verschoben und die Beans an anderer Stelle wurden gefunden und die Dinge begannen zu funktionieren. Anfängerfehler für mich.
Glaukommatos
2
Das Hinzufügen von @ComponentScan (basePackages = "com.base.package") hat es in meinem Fall gelöst
Shamli
Das hilft wirklich.
Madhu Tomy
12

SpringBoot-Entwickler empfehlen, Ihre Hauptanwendungsklasse in einem Root-Paket über anderen Klassen zu suchen. Durch die Verwendung eines Root-Pakets kann auch die Annotation @ComponentScan verwendet werden, ohne dass ein basePackage- Attribut angegeben werden muss. Detaillierte Informationen Stellen Sie jedoch sicher, dass das benutzerdefinierte Root-Paket vorhanden ist.

Torina
quelle
10

Dieselbe 404-Antwort, die ich nach der Ausführung des Dienstes mit dem folgenden Code erhalten habe

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

}

Antwort:

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

Nachdem ich es auf den folgenden Code geändert hatte, erhielt ich die richtige Antwort

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

}

Antwort:

{
"batchId": "DUE1529673844630",
"batchType": null,
"executionDate": null,
"status": "OPEN"
}
Mahender Ambala
quelle
1
Falls andere Leser es nicht sehen, @Controller->@RestController
Janac Meena
7

Ich hatte dieses Problem und Sie müssen nur Ihre Pakete reparieren. Wenn Sie dieses Projekt von http://start.spring.io/ heruntergeladen haben, haben Sie Ihre Hauptklasse in einem Paket. Wenn das Paket für die Hauptklasse beispielsweise "com.example" lautet, muss sich Ihr Controller im Paket "com.example.controller" befinden. Hoffe das hilft.

f.trajkovski
quelle
6

Es gibt zwei Methoden, um dies zu überwinden

  1. Platzieren Sie die Boot-Anwendung am Anfang der Paketstruktur und legen Sie den gesamten Controller darin ab.

    Beispiel:

    Paket com.spring.boot.app; - Sie starten die Anwendung (dh Hauptmethode -SpringApplication.run (App.class, args);)

    Sie ruhen Controller mit derselben Paketstruktur aus. Beispiel: Paket com.spring.boot.app.rest;

  2. Definieren Sie den Controller explizit im Bootup-Paket.

Methode 1 ist sauberer.

Mohammed Sarfaraz
quelle
1
Spring Boot hasst es, dass die Anwendungsklasse unter einem anderen Paket als dem Basispaket liegt. Wenn das Basispaket org.someapp ist und wenn wir es unter org.someapp.app ablegen, bombardiert es ..: - /
Priyank Thakkar
3

Sie müssen die Starter-Application-Klasse wie unten gezeigt ändern.

@SpringBootApplication

@EnableAutoConfiguration

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

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

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

Aktualisieren Sie die Paketstruktur für Controller, Service und Repository wie unten erwähnt.

Beispiel: REST-Controller

package com.nice.controller; -> Es muss geändert werden als
package com.nice.application.controller;

Sie müssen die richtige Paketstruktur für alle Pakete befolgen, die sich im Spring Boot MVC-Flow befinden.

Wenn Sie also die Paketstrukturen Ihres Projektpakets korrekt ändern, funktioniert Ihre Spring Boot-App ordnungsgemäß.

Anjan
quelle
3
EnableAutoConfiguration ist in @SpringBootApplication enthalten, daher ist es sinnlos, es hinzuzufügen.
Sofiane
1

Ersetzen @RequestMapping( "/item" )durch @GetMapping(value="/item", produces=MediaType.APPLICATION_JSON_VALUE).

Vielleicht hilft es jemandem.

Ihor Khomiak
quelle
1
es half mir zu erkennen, dass ich namestatt valuein der geschrieben hatte @GetMapping.
vortex.alex
0

Ich hatte genau den gleichen Fehler, ich gab kein Basispaket. Geben Sie das richtige Basispaket und lösen Sie es erneut.

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);
    }

}

Hinweis: Ohne .controller @ComponentScan (basePackages = "com.ymc.backend.controller"), da ich viele andere Komponentenklassen habe, die mein Projekt nicht scannt, wenn ich nur .controller gebe

Hier ist mein Controller-Beispiel:

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


}
Nabin Kumar Khatiwada
quelle
0

Manchmal verhält sich der Frühlingsstiefel komisch. Ich habe unten in der Anwendungsklasse angegeben und es funktioniert:

@ComponentScan("com.seic.deliveryautomation.controller")
Liebe Kumar
quelle
0

Ich habe das 404-Problem aufgrund der URL-Groß- / Kleinschreibung .

Zum Beispiel @RequestMapping(value = "/api/getEmployeeData",method = RequestMethod.GET)sollte mit zugegriffen werden http://www.example.com/api/getEmployeeData. Wenn wir verwendenhttp://www.example.com/api/getemployeedata , erhalten wir den Fehler 404.

Hinweis: http://www.example.comdient nur als Referenz, die ich oben erwähnt habe. Es sollte Ihr Domain-Name sein, unter dem Sie Ihre Anwendung gehostet haben.

Nach viel Mühe und Anwenden aller anderen Antworten in diesem Beitrag habe ich festgestellt, dass das Problem nur bei dieser URL liegt. Es könnte ein dummes Problem sein. Aber es hat meine 2 Stunden gekostet. Also ich hoffe es wird jemandem helfen.

Mahendran Sakkarai
quelle
0

Für mich habe ich Spring-Web anstelle des Spring-Boot-Starter-Web in meine pom.xml eingefügt

Wenn ich es von Spring-Web zu Spring-Boot-Starter-Web ersetze, werden alle Zuordnungen im Konsolenprotokoll angezeigt.

Sakirow
quelle
0

Es funktioniert auch, wenn wir Folgendes verwenden:

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

Es kann sein, dass auf Port 8080 etwas anderes ausgeführt wird und Sie versehentlich eine Verbindung herstellen.

Überprüfen Sie dies auf jeden Fall, insbesondere wenn Sie Docker haben, die andere Dienste aufrufen, die Sie nicht kontrollieren, und diese Dienste über den Port weiterleiten.

Brad Parks
quelle
0

Das Problem liegt in Ihrer Paketstruktur. Die Spring Boot-Anwendung verfügt über eine spezielle Paketstruktur, mit der der Spring-Kontext verschiedene Beans in seinem Kontext scannen und laden kann.

In com.nice.application befindet sich Ihre Hauptklasse und in com.nice.controller haben Sie Ihre Controller-Klassen.

Verschieben Sie Ihr com.nice.controller-Paket in com.nice.application, damit Spring auf Ihre Beans zugreifen kann.

Naresh Bhadke
quelle
-1

Sie können innerhalb des POM hinzufügen.

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

Platzieren Sie Ihre springbootapplication-Klasse im Root-Paket. Wenn sich Ihr Dienstcontroller beispielsweise im springBoot.xyz-Paket befindet, sollte sich Ihre Hauptklasse im springBoot-Paket befinden, da sonst die folgenden Pakete nicht durchsucht werden

ASG
quelle