Spring Boot: Tidak dapat mengakses REST Controller di localhost (404)

105

Saya mencoba untuk mengadaptasi contoh REST Controller di situs web Spring Boot. Sayangnya saya mendapat kesalahan berikut saat mencoba mengakses 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>

Aplikasi Pemula:

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

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

}

Saya membangun proyek ini dengan Maven. Memulai sebagai jar (spring-boot: run) dan juga di dalam IDE (Eclipse).

Log Konsol:

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

Apa yang saya coba sejauh ini:

  • Mengakses URL dengan nama aplikasi (InventoryApp)
  • Letakkan yang lain @RequestMapping("/")di tingkat kelas dariItemInventoryController

Sejauh yang saya mengerti, saya tidak memerlukan konteks aplikasi saat menggunakan Spring Boot. Apakah saya benar?

Apa lagi yang dapat saya lakukan untuk mengakses metode melalui URL?

mchlfchr.dll
sumber
Bagaimana Anda menjalankan aplikasi? Bisakah Anda memasukkan beberapa log?
wjans
Mencoba secara terpisah melalui Eclipse dan dengan mvn spring-boot: run (as jar). Lihat di atas untuk log (diedit)
mchlfchr
Dari log startup sepertinya tidak menemukan pengontrol Anda, di paket apa kelas pengontrol Anda?
MattR
1
Ada dalam paket terpisah. Kelas starter dengan metode utama ada di "aplikasi" sedangkan pengontrol ada di paket "pengontrol". Saya telah melihat contoh (bukan yang di spring.io), yang juga disusun dengan cara itu.
mchlfchr
4
Secara default, spring-boot akan memindai komponen dalam paket yang sama, atau paket "di bawah" (awalan yang sama) sebagai kelas aplikasi Anda. Jika tidak, Anda perlu memindai secara eksplisit, misalnya menggunakan @ComponentScan
MattR

Jawaban:

198

Coba tambahkan yang berikut ini ke kelas InventoryApp Anda

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

spring-boot akan memindai komponen dalam paket di bawah ini com.nice.application, jadi jika pengontrol Anda ada, com.nice.controllerAnda perlu memindai secara eksplisit.

MattR
sumber
Saya memiliki masalah yang sama. Saya mencoba dengan componentscan tetapi tidak ada :-( Pertanyaan saya: stackoverflow.com/questions/33000931/…
emoleumassi
1
harap dicatat bahwa @SpringBootApplicationtermasuk@Configuration
krzakov
9
Tampaknya paling mudah untuk meletakkan Aplikasi dalam paket "root", misalnya "org.whatever" dan pengontrol, layanan dalam sub-paket.
insan-e
7
Saya memiliki masalah yang sama tetapi sebelum datang ke solusi ini saya menemukannya ... Lebih lanjut. ambil kelas aplikasi boot musim semi Anda (di mana metode utama ditentukan) satu level ke atas ke paket pengontrol .. maka pengontrol akan terlihat untuk ini dan akan berfungsi
Tayab Hussain
1
Anda juga dapat menggunakan '@ComponentScan (basePackages = "com.nice.controller")'. Pemindaian default komponen dimulai pada jalur, di mana kelas App dan juga memindai paket-paket tambahan. Dalam hal ini, Anda tidak perlu menggunakan anotasi @ComponentScan. Itu dilakukan secara otomatis. Jika Anda memiliki lebih dari 1 pengontrol, Anda juga dapat memilikinya dalam paket yang berbeda, Anda dapat merantai mereka. Dalam hal ini, penting untuk menghindari konflik.
hariprasad
48

Menambahkan jawaban mattr ini:

Sebagaimana dinyatakan dalam sini , @SpringBootApplicationsecara otomatis memasukkan penjelasan yang diperlukan: @Configuration, @EnableAutoConfiguration, dan juga @ComponentScan; Namun, @ComponentScanhanya akan mencari komponen dalam paket yang sama dengan Aplikasi, dalam hal ini Anda com.nice.application, sedangkan pengontrol Anda berada di com.nice.controller. Itulah mengapa Anda mendapatkan 404 karena Aplikasi tidak menemukan pengontrol dalam applicationpaket.

cipley
sumber
5
Dalam hal ini belum sepenuhnya jelas dari penjelasan di atas, kelas dengan anotasi @SpringBootApplication harus DI ATAS atau pada level yang sama dalam struktur direktori Anda dengan hal-hal yang ingin Anda temukan. Misalnya, saya memiliki com.app.configuration dan com.app.controllers. Saya keliru memasukkan kelas Aplikasi saya ke com.app.configuration, dan semua yang lain di com.app.configuration bekerja dengan baik, tetapi tidak ada di com.app.controllers yang dimuat. Saya memindahkan kelas Aplikasi saya ke com.app dan kacang di tempat lain ditemukan dan semuanya mulai bekerja. Kesalahan pemula untukku.
glaukommatos
2
Menambahkan @ComponentScan (basePackages = "com.base.package") memecahkannya dalam kasus saya
Shamli
Ini sangat membantu.
Madhu Tomy
12

Pengembang SpringBoot merekomendasikan untuk mencari kelas aplikasi utama Anda dalam paket root di atas kelas lain. Menggunakan paket root juga memungkinkan anotasi @ComponentScan digunakan tanpa perlu menentukan atribut basePackage . Info lengkap Tapi pastikan bahwa paket root kustom ada.

torina
sumber
10

Respons 404 yang sama yang saya dapatkan setelah layanan dijalankan dengan kode di bawah ini

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

}

Tanggapan:

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

setelah mengubahnya menjadi kode di bawah ini saya menerima tanggapan yang tepat

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

}

Tanggapan:

{
"batchId": "DUE1529673844630",
"batchType": null,
"executionDate": null,
"status": "OPEN"
}
Mahender Ambala
sumber
1
Memetikan pembaca lain tidak melihatnya, @Controller->@RestController
Janac Meena
7

Saya mengalami masalah ini dan yang perlu Anda lakukan adalah memperbaiki paket Anda. Jika Anda mendownload proyek ini dari http://start.spring.io/ maka Anda memiliki kelas utama dalam beberapa paket. Misalnya jika paket untuk kelas utama adalah: "com.example" maka pengontrol Anda harus ada dalam paket: "com.example.controller". Semoga ini membantu.

f. trajkovski
sumber
6

Ada 2 cara untuk mengatasinya

  1. Tempatkan aplikasi boot di awal struktur paket dan letakkan semua pengontrol di dalamnya.

    Contoh:

    paket com.spring.boot.app; - Anda mem-boot aplikasi (yaitu Metode Utama -SpringApplication.run (App.class, args);)

    Anda Rest Controller dengan struktur paket yang sama Contoh: package com.spring.boot.app.rest;

  2. Tentukan secara eksplisit Controller dalam paket Bootup.

Metode 1 lebih bersih.

Mohammed Sarfaraz
sumber
1
spring boot membenci aplikasi kelas yang berada di bawah beberapa paket selain paket dasar .. jika paket dasar adalah org.someapp dan jika kita meletakkannya di bawah org.someapp.app itu bom ..: - /
Priyank Thakkar
3

Anda perlu mengubah kelas Aplikasi Pemula seperti yang ditunjukkan di bawah ini.

@SpringBootApplication

@EnableAutoConfiguration

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

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

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

Dan perbarui struktur paket Pengontrol, Layanan, dan Repositori seperti yang saya sebutkan di bawah ini.

Contoh: REST-Controller

package com.nice.controller; -> Itu harus dimodifikasi sebagai
package com.nice.application.controller;

Anda harus mengikuti struktur paket yang tepat untuk semua paket yang ada dalam aliran MVC Spring Boot.

Jadi, Jika Anda memodifikasi struktur paket bundel proyek dengan benar, aplikasi boot musim semi Anda akan bekerja dengan benar.

Anjan
sumber
3
EnableAutoConfiguration disertakan dalam @SpringBootApplication jadi tidak ada gunanya menambahkannya.
Sofiane
1

Ganti @RequestMapping( "/item" )dengan@GetMapping(value="/item", produces=MediaType.APPLICATION_JSON_VALUE) .

Mungkin itu akan membantu seseorang.

Ihor Khomiak
sumber
1
itu membantu saya untuk menyadari bahwa saya telah menulis namealih-alih valuedi @GetMapping.
vortex.alex
0

Saya mengalami kesalahan yang sama persis, saya tidak memberikan paket dasar. Memberikan paket dasar yang benar, menyelesaikannya kembali.

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

}

Catatan: tidak termasuk .controller @ComponentScan (basePackages = "com.ymc.backend.controller") karena saya memiliki banyak kelas komponen lain yang proyek saya tidak memindai jika saya hanya memberikan .controller

Berikut adalah contoh pengontrol saya:

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
sumber
0

Terkadang sepatu bot musim semi berperilaku aneh. Saya tentukan di bawah ini di kelas aplikasi dan berhasil:

@ComponentScan("com.seic.deliveryautomation.controller")
Cintai Kumar
sumber
0

Saya mendapat masalah 404, karena Url Case Sensitivity .

Misalnya @RequestMapping(value = "/api/getEmployeeData",method = RequestMethod.GET)harus diakses menggunakan http://www.example.com/api/getEmployeeData. Jika kami menggunakanhttp://www.example.com/api/getemployeedata , kami akan mendapatkan kesalahan 404.

Catatan: http://www.example.comhanya untuk referensi yang saya sebutkan di atas. Ini harus menjadi nama domain Anda tempat Anda meng-host aplikasi Anda.

Setelah banyak perjuangan dan menerapkan semua jawaban lain di posting ini, saya mendapat bahwa masalahnya hanya dengan url itu. Ini mungkin masalah konyol. Tapi itu menghabiskan waktu 2 jam saya. Jadi saya berharap ini akan membantu seseorang.

Mahendran Sakkarai
sumber
0

bagi saya, saya menambahkan spring-web alih-alih spring-boot-starter-web ke pom.xml saya

ketika saya menggantinya dari spring-web ke spring-boot-starter-web, semua pemetaan ditampilkan di log konsol.

sakirow
sumber
0

Ini juga berfungsi jika kita menggunakan sebagai berikut:

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

Bisa jadi ada sesuatu yang lain sedang berjalan pada port 8080, dan Anda benar-benar menghubungkannya secara tidak sengaja.

Pastikan periksa itu, terutama jika Anda memiliki pekerja galangan yang membawa layanan lain yang tidak Anda kontrol, dan meneruskan port layanan tersebut.

Brad Parks
sumber
0

Masalahnya ada pada struktur paket Anda. Aplikasi Spring Boot memiliki struktur paket khusus yang memungkinkan konteks pegas memindai dan memuat berbagai kacang dalam konteksnya.

Di com.nice.application adalah tempat Kelas Utama Anda dan di com.nice.controller, Anda memiliki kelas pengontrol.

Pindahkan paket com.nice.controller Anda ke com.nice.application sehingga Spring dapat mengakses kacang Anda.

Naresh Bhadke
sumber
-1

Anda dapat menambahkan di dalam POM.

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

Tempatkan kelas aplikasi springboot Anda dalam paket root misalnya jika layanan Anda, pengontrol ada dalam paket springBoot.xyz maka kelas utama Anda harus ada dalam paket springBoot jika tidak maka tidak akan memindai paket di bawah ini

ASG
sumber