Spring Boot: impossible d'accéder au contrôleur REST sur localhost (404)

105

J'essaie d'adapter l'exemple du contrôleur REST sur le site Web de Spring Boot. Malheureusement, j'ai l'erreur suivante lorsque j'essaie d'accéder aulocalhost:8080/item URL.

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

Application de démarrage:

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

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

}

Je construis ce projet avec Maven. Lancez-le en tant que jar (spring-boot: run) et aussi dans l'IDE (Eclipse).

Journal de la console:

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

Ce que j'ai essayé jusqu'à présent:

  • Accéder à l'URL avec le nom de l'application (InventoryApp)
  • Mettez un autre @RequestMapping("/")au niveau de la classeItemInventoryController

Pour autant que je sache, je n'aurai pas besoin d'un contexte d'application lors de l'utilisation de Spring Boot. Ai-je raison?

Que puis-je faire d'autre pour accéder à la méthode via une URL?

mchlfchr
la source
Comment exécutez-vous l'application? Pouvez-vous peut-être inclure des journaux?
wjans
Je l'ai essayé séparément via Eclipse et avec mvn spring-boot: run (as jar). Voir ci-dessus pour les journaux (modifiés)
mchlfchr
Dans le journal de démarrage, il ne semble pas qu'il trouve votre contrôleur, dans quel package se trouve votre classe de contrôleur?
MattR
1
C'est dans un emballage séparé. La classe de démarrage avec la méthode principale est dans "application" tandis que le contrôleur est dans le package "controller". J'ai vu des exemples (pas ceux de spring.io), qui étaient également structurés de cette manière.
mchlfchr
4
Par défaut, spring-boot recherchera les composants dans le même package, ou les packages "ci-dessous" (même préfixe) que votre classe d'application. Sinon, vous devez les rechercher explicitement, par exemple en utilisant @ComponentScan
MattR

Réponses:

198

Essayez d'ajouter ce qui suit à votre classe InventoryApp

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

spring-boot recherchera les composants dans les packages ci com.nice.application- dessous , donc si votre contrôleur est dans com.nice.controllervous devez le rechercher explicitement.

MattR
la source
J'ai les mêmes problèmes. J'essaye avec le componentscan mais rien :-( Hier ma question: stackoverflow.com/questions/33000931/…
emoleumassi
1
s'il vous plaît noter que @SpringBootApplicationcomprend@Configuration
krzakov
9
Il semble plus simple de mettre l'Application dans le package "root", par exemple "org.wwhat" et les contrôleurs, services dans des sous-packages.
insan-e
7
J'ai le même problème mais avant d'arriver à cette solution, je l'ai trouvée ... prenez votre classe d'application de démarrage de printemps (dans laquelle la méthode principale est définie) un niveau jusqu'au paquet de contrôleur .. alors les contrôleurs seront visibles pour cela et fonctionneront
Tayab Hussain
1
Vous pouvez également utiliser '@ComponentScan (basePackages = "com.nice.controller")'. L'analyse par défaut des composants commence sur le chemin, où se trouve la classe App et analyse également les packages subsidiaires. Dans ce cas, vous n'avez pas besoin d'utiliser l'annotation @ComponentScan. Cela se fait automatiquement. Si vous avez plus d'un contrôleur, il est possible de les avoir dans différents packages également, vous pouvez les enchaîner. Dans ce cas, il est important d'éviter les conflits.
hariprasad
48

Ajout à la réponse de MattR:

comme indiqué ici , @SpringBootApplicationinsère automatiquement les annotations nécessaires:@Configuration , @EnableAutoConfigurationet aussi @ComponentScan; cependant, le @ComponentScanne recherchera que les composants dans le même package que l'application, dans ce cas votre com.nice.application, alors que votre contrôleur réside dans com.nice.controller. C'est pourquoi vous obtenez 404 car l'application n'a pas trouvé le contrôleur dans le applicationpackage.

Cipley
la source
5
Au cas où cela ne serait pas déjà tout à fait clair à partir de l'explication ci-dessus, la classe avec l'annotation @SpringBootApplication doit être AU-DESSUS ou au même niveau dans votre structure de répertoires que les éléments que vous souhaitez qu'elle trouve. Par exemple, j'avais com.app.configuration et com.app.controllers. J'ai mis par erreur ma classe Application dans com.app.configuration, et tout le reste dans com.app.configuration fonctionnait bien, mais rien dans com.app.controllers ne se chargeait. J'ai déplacé ma classe Application dans com.app et les beans ont été trouvés ailleurs et les choses ont commencé à fonctionner. Erreur de recrue pour moi.
glaukommatos
2
L'ajout de @ComponentScan (basePackages = "com.base.package") l'a résolu dans mon cas
Shamli
Cela aide vraiment.
Madhu Tomy
12

Les développeurs SpringBoot recommandent de localiser votre classe d'application principale dans un package racine au-dessus des autres classes. L'utilisation d'un package racine permet également d'utiliser l'annotation @ComponentScan sans avoir besoin de spécifier un attribut basePackage . Informations détaillées Mais assurez-vous que le package racine personnalisé existe.

torina
la source
10

Même réponse 404 que j'ai eu après le service exécuté avec le code ci-dessous

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

}

Réponse:

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

après l'avoir changé en code ci-dessous, j'ai reçu une réponse appropriée

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

}

Réponse:

{
"batchId": "DUE1529673844630",
"batchType": null,
"executionDate": null,
"status": "OPEN"
}
Mahender Ambala
la source
1
Incase les autres lecteurs ne le voient pas, @Controller->@RestController
Janac Meena
7

J'ai eu ce problème et ce que vous devez faire est de corriger vos paquets. Si vous avez téléchargé ce projet depuis http://start.spring.io/, alors vous avez votre classe principale dans un package. Par exemple, si le package de la classe principale est: "com.example" alors et votre contrôleur doit être dans le package: "com.example.controller". J'espère que cela t'aides.

f.trajkovski
la source
6

Il existe 2 méthodes pour surmonter cela

  1. Placez l'application de démarrage au début de la structure du package et placez tous les contrôleurs à l'intérieur.

    Exemple :

    package com.spring.boot.app; - Vous démarrez l'application (c'est-à-dire la méthode principale -SpringApplication.run (App.class, args);)

    Vous restez Controller avec la même structure de package Exemple: package com.spring.boot.app.rest;

  2. Définissez explicitement le contrôleur dans le package Bootup.

La méthode 1 est plus propre.

Mohammed Sarfaraz
la source
1
spring boot déteste la classe d'application se trouvant sous un package autre que le package de base..si le package de base est org.someapp et si nous le mettons sous org.someapp.app, il bombarde ..: - /
Priyank Thakkar
3

Vous devez modifier la classe Starter-Application comme indiqué ci-dessous.

@SpringBootApplication

@EnableAutoConfiguration

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

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

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

Et mettez à jour la structure des packages Controller, Service et Repository comme je l'ai mentionné ci-dessous.

Exemple: REST-Controller

package com.nice.controller; -> Il doit être modifié comme
package com.nice.application.controller;

Vous devez suivre la structure de package appropriée pour tous les packages qui se trouvent dans le flux Spring Boot MVC.

Donc, si vous modifiez correctement les structures de package de votre projet, votre application Spring Boot fonctionnera correctement.

Anjan
la source
3
EnableAutoConfiguration est inclus dans @SpringBootApplication, il est donc inutile de l'ajouter.
Sofiane
1

Remplacer @RequestMapping( "/item" )par@GetMapping(value="/item", produces=MediaType.APPLICATION_JSON_VALUE) .

Peut-être que cela aidera quelqu'un.

Ihor Khomiak
la source
1
cela m'a aidé à reconnaître que j'avais écrit nameau lieu de valuedans le @GetMapping.
vortex.alex
0

J'ai eu exactement la même erreur, je ne donnais pas de package de base. Donner le paquet de base correct, le résoudre.

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

}

Remarque: sans compter .controller @ComponentScan (basePackages = "com.ymc.backend.controller") car j'ai beaucoup d'autres classes de composants que mon projet ne scanne pas si je donne juste .controller

Voici mon exemple de contrôleur:

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
la source
0

Parfois, la botte à ressort se comporte bizarrement. J'ai spécifié ci-dessous dans la classe d'application et cela fonctionne:

@ComponentScan("com.seic.deliveryautomation.controller")
Aime Kumar
la source
0

J'ai eu le problème 404, à cause de la sensibilité à la casse de l' URL .

Par exemple, @RequestMapping(value = "/api/getEmployeeData",method = RequestMethod.GET)doit être accessible en utilisant http://www.example.com/api/getEmployeeData. Si nous utilisonshttp://www.example.com/api/getemployeedata , nous obtiendrons l'erreur 404.

Remarque: http://www.example.comest juste pour référence que j'ai mentionné ci-dessus. Il doit s'agir de votre nom de domaine où vous avez hébergé votre application.

Après beaucoup de lutte et après avoir appliqué toutes les autres réponses de cet article, j'ai compris que le problème venait uniquement de cette URL. Cela pourrait être un problème idiot. Mais cela m'a coûté 2 heures. J'espère donc que cela aidera quelqu'un.

Mahendran Sakkarai
la source
0

pour moi, j'ajoutais spring-web au lieu de spring-boot-starter-web dans mon pom.xml

quand je le remplace de spring-web à spring-boot-starter-web, tout le mappage est affiché dans le journal de la console.

Sakirow
la source
0

Cela fonctionne également si nous utilisons comme suit:

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

Il se peut que quelque chose d'autre fonctionne sur le port 8080 et que vous vous y connectez par erreur.

Vérifiez certainement cela, surtout si vous avez des dockers qui proposent d'autres services que vous ne contrôlez pas et qui transfèrent ces services.

Brad Parks
la source
0

Le problème vient de la structure de votre package. Spring Boot Application a une structure de package spécifique pour permettre au contexte Spring d'analyser et de charger divers beans dans son contexte.

Dans com.nice.application est l'endroit où se trouve votre classe principale et dans com.nice.controller, vous avez vos classes de contrôleur.

Déplacez votre package com.nice.controller dans com.nice.application afin que Spring puisse accéder à vos beans.

Naresh Bhadke
la source
-1

Vous pouvez ajouter à l'intérieur du POM.

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

Placez votre classe springbootapplication dans le package racine.Par exemple, si votre service, le contrôleur est dans le package springBoot.xyz, votre classe principale devrait être dans le package springBoot, sinon il n'analysera pas les packages ci-dessous

ASG
la source