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

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-11 18:55:34  来源:igfitidea点击:

Rest Controller not recognizing GET request in Spring Boot App

javamavenspring-mvcspring-bootspring-restcontroller

提问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项目:

Maven Java Project Structure

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

enter image description here

在此处输入图片说明

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 

Rest App Browser

休息应用浏览器

采纳答案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 @ResponseBodyAnnotation

您可以尝试添加@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 项目结构:

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.

这是后面发生的事情。

@SpringBootApplicationannotation is a combination of @Configuration@EnableAutoConfiguration@ComponentScan.

@SpringBootApplication注释是 的组合@Configuration@EnableAutoConfiguration@ComponentScan

@ComponentScanwithout arguments tells the framework to find components/beans in the same package and its sub-packages.

@ComponentScan不带参数告诉框架在同一个包及其子包中查找组件/bean。

Your Applicationclass which is annotated with @SpringBootApplicationis 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 CircleControlleris inside package com.nomad.dubbed.controllerwhich 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.*)。但是您CircleControllercom.nomad.dubbed.controller默认情况下不会扫描的包内。您的存储库也位于默认扫描包之外,因此 spring 框架也不会发现它们。

So what to do now?, you have two options.

那么现在该怎么办?,您有两个选择。

Option 1

选项1

Move the Applicationclass to the top directory(package). In your case com.nomad.dubbedpackage. 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 @ComponentScanannotation with basePackagesargument, along with the @SpringBootApplicationin your Applicationclass 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

谢谢!百吉拉达