Java Rest Controller 无法识别 Spring Boot App 中的 GET 请求
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/37011790/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Rest Controller not recognizing GET request in Spring Boot App
提问by gkc123
I am trying to implement simple demo MVC app with Spring Boot but I get 404 error while executing the application. The uri is `http://localhost:8080/' which is to display all the rows in a table called circle.
我正在尝试使用 Spring Boot 实现简单的演示 MVC 应用程序,但在执行应用程序时出现 404 错误。uri 是` http://localhost:8080/',它用于显示一个名为 circle 的表中的所有行。
- Spring Boot : 1.3.3.RELEASE
- Java Version : 1.8.0_65
- Database : Apache Derby 10.12.1.1
- 春季启动:1.3.3.RELEASE
- Java 版本:1.8.0_65
- 数据库:Apache Derby 10.12.1.1
Maven Java Project:
Maven Java项目:
Application.java
应用程序.java
package com.nomad.dubbed.app;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class Application {
public static void main(String[] args){
SpringApplication.run(Application.class, args);
}
}
CircleController.java
圆控制器.java
package com.nomad.dubbed.controller;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
import com.nomad.dubbed.dao.CircleService;
import com.nomad.dubbed.model.Circle;
@RestController
@RequestMapping("/")
public class CircleController {
@Autowired
private CircleService circleService;
@RequestMapping(method=RequestMethod.GET)
public List<Circle> getAll() {
return circleService.getAll();
}
}
CircleRepository.java
CircleRepository.java
package com.nomad.dubbed.dao;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;
import com.nomad.dubbed.model.Circle;
@Repository
public interface CircleRepository extends JpaRepository<Circle, Integer> {
}
CircleService.java
CircleService.java
package com.nomad.dubbed.dao;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import com.nomad.dubbed.model.Circle;
@Service
public class CircleService {
@Autowired
private CircleRepository circleRepository;
@Transactional(propagation=Propagation.REQUIRED)
public List<Circle> getAll(){
return circleRepository.findAll();
}
}
Circle.java
圆环.java
package com.nomad.dubbed.model;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Table;
@Entity
@Table(name="circle")
public class Circle {
@Id
@GeneratedValue(strategy=GenerationType.IDENTITY)
private int id;
private String name;
public Circle(int id, String name) {
super();
this.id = id;
this.name = name;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
application.properties
应用程序属性
spring.datasource.url=jdbc:derby://localhost:1527/db
spring.datasource.driverClassName=org.apache.derby.jdbc.ClientDriver
logging.level.org.springframework.web:DEBUG
logging.level.org.hibernate:DEBUG
pom.xml
pom.xml
<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>com.nomad.dubbed</groupId>
<artifactId>spring-boot-mvc</artifactId>
<version>0.0.1-SNAPSHOT</version>
<properties>
<derby-client.version>10.11.1.1</derby-client.version>
</properties>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.3.3.RELEASE</version>
<relativePath />
</parent>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-remote-shell</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>org.apache.derby</groupId>
<artifactId>derbyclient</artifactId>
<version>${derby-client.version}</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<finalName>spring-boot-mvc</finalName>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
Database is up and running, there are 5 rows in the table circle:
数据库启动并运行,表圈有5行:
The default uri (/beans, /health..) works fine but the implemented controller is not recognized. There is no error of such displayed in the console, below is the dump of logs printed in console after I send the request.
默认 uri (/beans, /health..) 工作正常,但无法识别实现的控制器。控制台中没有显示此类错误,以下是我发送请求后在控制台中打印的日志转储。
2016-05-03 14:17:26.594 DEBUG 659 --- [nio-8080-exec-3] o.s.web.servlet.DispatcherServlet : DispatcherServlet with name 'dispatcherServlet' processing GET request for [/]
2016-05-03 14:17:26.596 DEBUG 659 --- [nio-8080-exec-3] s.w.s.m.m.a.RequestMappingHandlerMapping : Looking up handler method for path /
2016-05-03 14:17:26.596 DEBUG 659 --- [nio-8080-exec-3] s.w.s.m.m.a.RequestMappingHandlerMapping : Did not find handler method for [/]
2016-05-03 14:17:26.597 DEBUG 659 --- [nio-8080-exec-3] o.s.w.s.handler.SimpleUrlHandlerMapping : Matching patterns for request [/] are [/**]
2016-05-03 14:17:26.597 DEBUG 659 --- [nio-8080-exec-3] o.s.w.s.handler.SimpleUrlHandlerMapping : URI Template variables for request [/] are {}
2016-05-03 14:17:26.597 DEBUG 659 --- [nio-8080-exec-3] o.s.w.s.handler.SimpleUrlHandlerMapping : Mapping [/] to HandlerExecutionChain with handler [ResourceHttpRequestHandler [locations=[ServletContext resource [/], class path resource [META-INF/resources/], class path resource [resources/], class path resource [static/], class path resource [public/]], resolvers=[org.springframework.web.servlet.resource.PathResourceResolver@6c13019c]]] and 1 interceptor
2016-05-03 14:17:26.597 DEBUG 659 --- [nio-8080-exec-3] o.s.web.servlet.DispatcherServlet : Last-Modified value for [/] is: -1
2016-05-03 14:17:26.597 DEBUG 659 --- [nio-8080-exec-3] o.s.web.servlet.DispatcherServlet : Null ModelAndView returned to DispatcherServlet with name 'dispatcherServlet': assuming HandlerAdapter completed request handling
2016-05-03 14:17:26.597 DEBUG 659 --- [nio-8080-exec-3] o.s.web.servlet.DispatcherServlet : Successfully completed request
2016-05-03 14:17:26.597 DEBUG 659 --- [nio-8080-exec-3] o.s.web.servlet.DispatcherServlet : DispatcherServlet with name 'dispatcherServlet' processing GET request for [/error]
2016-05-03 14:17:26.600 DEBUG 659 --- [nio-8080-exec-3] s.w.s.m.m.a.RequestMappingHandlerMapping : Looking up handler method for path /error
2016-05-03 14:17:26.600 DEBUG 659 --- [nio-8080-exec-3] s.w.s.m.m.a.RequestMappingHandlerMapping : Returning handler method [public org.springframework.web.servlet.ModelAndView org.springframework.boot.autoconfigure.web.BasicErrorController.errorHtml(javax.servlet.http.HttpServletRequest,javax.servlet.http.HttpServletResponse)]
2016-05-03 14:17:26.600 DEBUG 659 --- [nio-8080-exec-3] o.s.web.servlet.DispatcherServlet : Last-Modified value for [/error] is: -1
2016-05-03 14:17:26.601 DEBUG 659 --- [nio-8080-exec-3] o.s.w.s.v.ContentNegotiatingViewResolver : Requested media types are [text/html, text/html;q=0.8] based on Accept header types and producible media types [text/html])
2016-05-03 14:17:26.601 DEBUG 659 --- [nio-8080-exec-3] o.s.w.s.v.ContentNegotiatingViewResolver : Returning [org.springframework.boot.autoconfigure.web.ErrorMvcAutoConfiguration$SpelView@2f5f8d71] based on requested media type 'text/html'
2016-05-03 14:17:26.601 DEBUG 659 --- [nio-8080-exec-3] o.s.web.servlet.DispatcherServlet : Rendering view [org.springframework.boot.autoconfigure.web.ErrorMvcAutoConfiguration$SpelView@2f5f8d71] in DispatcherServlet with name 'dispatcherServlet'
2016-05-03 14:17:26.601 DEBUG 659 --- [nio-8080-exec-3] o.s.web.servlet.DispatcherServlet : Successfully completed request
采纳答案by Lutz Müller
use a different url for your controller. "/" in spring-boot maps to static resources located in META-INF/resources and src/main/resources/static/ .
为您的控制器使用不同的 url。spring-boot 中的“/”映射到位于 META-INF/resources 和 src/main/resources/static/ 中的静态资源。
edit: forget above and do the following in your application class:
编辑:忘记上面的内容并在您的应用程序类中执行以下操作:
Application.java
应用程序.java
package com.nomad.dubbed.app;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
@ComponentScan("com.nomad.dubbed")
public class Application {
public static void main(String[] args){
SpringApplication.run(Application.class, args);
}
}
your rest controller is not discovered by spring-boots component scan. according to this doc http://docs.spring.io/spring-boot/docs/current/reference/html/… spring scans the packages below the package where the class with the @SpringBootApplication annotation resides. your controller is located in a parallel package.
spring-boots 组件扫描未发现您的休息控制器。根据这个文档http://docs.spring.io/spring-boot/docs/current/reference/html/… spring 扫描带有 @SpringBootApplication 注释的类所在的包下面的包。您的控制器位于并行包中。
回答by jstuartmilne
Could you try adding the @ResponseBody
Annotation
您可以尝试添加@ResponseBody
注释吗
@RequestMapping(method=RequestMethod.GET)
@ResponseBody
public List<Circle> getAll() {
return circleService.getAll();
}
回答by gkc123
I have to research more why spring - boot failed to recognize controller with the original package structure. I dumped all the java classes into one package and finally got the demo project running.
我必须进一步研究为什么 spring-boot 无法识别具有原始包结构的控制器。我将所有的 java 类都转储到一个包中,最后让演示项目运行起来。
Modified Java Project Structure:
修改后的 Java 项目结构:
The CircleController.java class was also modified. I have all the records deleted from the circle table without mentioning specific Request Method, method=RequestMethod.GET
.
CircleController.java 类也被修改。我已经从圆表中删除了所有记录,而没有提到具体的请求方法,method=RequestMethod.GET
.
package com.nomad.dubbed.app;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class CircleController {
@Autowired
private CircleService circleService;
@RequestMapping(value="/circles", method=RequestMethod.GET)
public List<Circle> getAll() {
return circleService.getAll();
}
}
回答by mani
I had the same problem and I added @ComponentScan(basePackages = "package.name")in the Application class. After that my rest controller was recognized.
我遇到了同样的问题,我在 Application 类中添加了@ComponentScan(basePackages = "package.name")。之后,我的休息控制器被识别出来。
package com.nomad.dubbed.app;
包 com.nomad.dubbed.app;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
@ComponentScan(basePackages = "com.spring.basepkg")
public class Application {
public static void main(String[] args){
SpringApplication.run(Application.class, args);
}
}
回答by Chinmay Biswal
In my opinion, this visibility problem comes when we leave the component scan to Spring which has a particular way of looking for the classes using standard convention. In this scenario as the Starter class(Application)is in com.nomad.dubbed.app package, putting Controller one level below will help Spring to find the classes using the default component scan mechanism. Putting CircleController under com.nomad.dubbed.app.controller should solve the issue.
在我看来,当我们将组件扫描留给 Spring 时,就会出现这种可见性问题,Spring 具有使用标准约定查找类的特定方式。在这个场景中,由于 Starter 类(应用程序)在 com.nomad.dubbed.app 包中,将 Controller 放在下面一层将帮助 Spring 使用默认的组件扫描机制找到类。将 CircleController 放在 com.nomad.dubbed.app.controller 下应该可以解决问题。
回答by Pooja
I had a similar issue. Adding the annotation @SpringBootApplication(scanBasePackages={"com.nomad.dubbed"})on the Application class worked for me.
我有一个类似的问题。在 Application 类上添加注释@SpringBootApplication(scanBasePackages={"com.nomad.dubbed"})对我有用。
回答by Johna
This what happens behind.
这是后面发生的事情。
@SpringBootApplication
annotation is a combination of @Configuration
@EnableAutoConfiguration
@ComponentScan
.
@SpringBootApplication
注释是 的组合@Configuration
@EnableAutoConfiguration
@ComponentScan
。
@ComponentScan
without arguments tells the framework to find components/beans in the same package and its sub-packages.
@ComponentScan
不带参数告诉框架在同一个包及其子包中查找组件/bean。
Your Application
class which is annotated with @SpringBootApplication
is in the package com.nomad.dubbed.app
. So it scans that package and its sub-packages under it (like com.nomad.dubbed.app.*
). But your CircleController
is inside package com.nomad.dubbed.controller
which is not scanned by default. Your repositories too fall outside the default scan packages, so they too will not be discovered by spring framework.
你的Application
类都被注解@SpringBootApplication
在包com.nomad.dubbed.app
。因此它会扫描该包及其下的子包(如com.nomad.dubbed.app.*
)。但是您CircleController
在com.nomad.dubbed.controller
默认情况下不会扫描的包内。您的存储库也位于默认扫描包之外,因此 spring 框架也不会发现它们。
So what to do now?, you have two options.
那么现在该怎么办?,您有两个选择。
Option 1
选项1
Move the Application
class to the top directory(package). In your case com.nomad.dubbed
package. Then, since all controllers and other repositories are in sub-packages, they will be discovered by the framework.
将Application
类移动到顶级目录(包)。在你的情况下com.nomad.dubbed
包。然后,由于所有控制器和其他存储库都在子包中,它们将被框架发现。
Option 2
选项 2
Use @ComponentScan
annotation with basePackages
argument, along with the @SpringBootApplication
in your Application
class like below.
使用@ComponentScan
注释与basePackages
论证,与一起@SpringBootApplication
在你的Application
类像下面。
@SpringBootApplication
@ComponentScan(basePackages="com.nomad.dubbed")
public class Application {
public static void main(String[] args){
SpringApplication.run(Application.class, args);
}
}
回答by Ankita Chaturvedi
We should not use @ComponentScan annotation with @SpringBootApplication as that's not the right practice. @SpringBootApplication is a combination of 03 annotations @ComponentScan, @EnableAutoConfiguration and @Configuration.
我们不应该将 @ComponentScan 注释与 @SpringBootApplication 一起使用,因为这不是正确的做法。@SpringBootApplication 是03注解@ComponentScan、@EnableAutoConfiguration和@Configuration的组合。
Answer is Main class which has @SpringBootApplication annotation should be in parent/super package. for eg - com.spring.learning is a parent package and childs are com.spring.learning.controller, com.spring.learning.service, com.spring.learning.pojo Hence it scans its package and sub packages. This is the right practice to do. Project layout or structure is a prominent concept in Spring Boot.
答案是具有 @SpringBootApplication 注释的 Main 类应该在父/超级包中。例如 - com.spring.learning 是父包,子包是 com.spring.learning.controller, com.spring.learning.service, com.spring.learning.pojo 因此它扫描它的包和子包。这是正确的做法。项目布局或结构是 Spring Boot 中的一个突出概念。
回答by Aks00747
actually springboots scans all of its components under you core package like example:
实际上,springboots 会扫描您核心包下的所有组件,例如:
package com.nomad.dubbed.app;
包 com.nomad.dubbed.app;
if you add controllers, services, dao packages under com.nomad.dubbed.app.controllers, com.nomad.dubbed.app.services, com.nomad.dubbed.app.dao.
如果在 com.nomad.dubbed.app.controllers、com.nomad.dubbed.app.services、com.nomad.dubbed.app.dao 下添加控制器、服务、dao 包。
then you can easily run your rest controller, but if you add all packages parallel to your core springboot package like com.nomad.dubbed.controllers, com.nomad.dubbed.services.
那么你可以轻松地运行你的 rest 控制器,但是如果你将所有包添加到你的核心 springboot 包中,比如 com.nomad.dubbed.controllers、com.nomad.dubbed.services。
then you need to scan for @ComponentScan({"com.nomad.dubbed.controllers","com.nomad.dubbed.services"})
那么你需要扫描@ComponentScan({"com.nomad.dubbed.controllers","com.nomad.dubbed.services"})
if you choose to go for componentscan then you have to also scan for springboot application package as well.
如果您选择使用componentscan,那么您还必须扫描springboot 应用程序包。
so best way is create all the packages under spring boot application dubbed.app.xyz...
所以最好的方法是在 spring boot 应用程序 dubbed.app.xyz 下创建所有包...
回答by BAGEERADHA
please check that the your controller classes are in sub packages.
请检查您的控制器类是否在子包中。
For example, if the main class is com.myapppackage, then controller class is either in the same package or is in sub package like com.myapp.controllers. Spring Framework will scan root package and then all its sub packages. In this case things will just work and you would not need to use @ComponentScan.
例如,如果主类是com.myapp包,那么控制器类要么在同一个包中,要么在像com.myapp.controllers这样的子包中。Spring Framework 将扫描根包,然后扫描它的所有子包。在这种情况下,事情会正常工作,您不需要使用@ComponentScan。
If you place the main class in com.myappand other beans/controllers which you want to be autowired you place in a different package like com.beans which is not a sub package of com.myapp, then you will experience an issue when beans could not be found.
如果您将主类放在com.myapp 中,而将其他想要自动装配的 bean/控制器放在不同的包中,例如 com.beans,它不是 com.myapp 的子包,那么当 bean找不到。
Thanks! Bageeradha
谢谢!百吉拉达