java Spring 控制器被调用但返回 404

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/48457939/
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-11-03 10:04:26  来源:igfitidea点击:

Spring controller gets invoked but returns 404

javaspring

提问by wesleyy

I am writing a Spring Boot application. I have written a simple controller that gets invoked whenever the endpoint is hit, but it still returns status 404 and not the specified return value.

我正在编写一个 Spring Boot 应用程序。我已经编写了一个简单的控制器,它在端点被命中时被调用,但它仍然返回状态 404 而不是指定的返回值。

HelloController

你好控制器

@Controller
public class MessageRequestController {

    @RequestMapping(method = RequestMethod.GET, value = "/hello", produces = "application/json")
    public String hello() {
        System.out.println("Hit me!");
        return "Hello, you!";
    }
}

Now whenever I call localhost:8080/hello, I see the console log "Hit me!", but "Hello, you!"is never returned. Postman outputs:

现在每当我打电话时localhost:8080/hello,我都会看到控制台日志"Hit me!",但"Hello, you!"永远不会返回。邮递员输出:

{
    "timestamp": 1516953147719,
    "status": 404,
    "error": "Not Found",
    "message": "No message available",
    "path": "/hello"
}

Application.java

应用程序.java

@SpringBootApplication
@ComponentScan({"com.sergialmar.wschat"}) // this is the root package of everything
@EntityScan("com.sergialmar.wschat")
public class Application {

    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }
}

回答by Saravana

Change your method return a ResponseEntity<T>

改变你的方法返回一个 ResponseEntity<T>

@RequestMapping(method = RequestMethod.GET, value = "/hello", produces = "application/json")
    public ResponseEntity<String> hello() {
        System.out.println("Hit me!");
        return new ResponseEntity<String>("Hello, you!", HttpStatus.OK);
    }

or change the controller to RestController

或将控制器更改为 RestController

@RestController
public class MessageRequestController {...}

CURL

卷曲

ubuntu:~$ curl -X GET localhost:8080/hello
Hello, you!

回答by Marc Tarin

Short version:

简洁版本:

Annotate your endpoint method with ResponseBodyto bind the return value to the response body.

使用ResponseBody注释端点方法以将返回值绑定到响应正文。

@Controller
public class MessageRequestController {

    @RequestMapping(method = RequestMethod.GET, value = "/hello", produces = "application/json")
    @ResponseBody
    public String hello() {
        System.out.println("Hit me!");
        return "Hello, you!";
    }

}

You can instead annotate your class with RestControllerinstead of Controllerto apply ResponseBodyto each method of the class.

您可以改为使用RestController注释您的类,而不是Controller应用于ResponseBody类的每个方法。

@RestController
public class MessageRequestController {

    @RequestMapping(method = RequestMethod.GET, value = "/hello", produces = "application/json")
    public String hello() {
        System.out.println("Hit me!");
        return "Hello, you!";
    }

}

With @Controller, you use the default model-view from Spring Web MVC, and you're actually telling spring to render the view called Hello, you!.tmlfrom your resources directory (src/main/resources/templatesfor a Spring Boot project, if I remember correctly).

使用@Controller,您使用Spring Web MVC的默认模型视图,并且您实际上是在告诉 spring 呈现Hello, you!.tml从您的资源目录调用的视图(src/main/resources/templates对于 Spring Boot 项目,如果我没记错的话)。

You can read this articlefor more information about the Spring MVC REST Workflow.

您可以阅读本文以了解有关 Spring MVC REST 工作流的更多信息。

Once you're more familiar with those concepts, you can even further customize your endpoint method using ResponseEntity.

一旦您更熟悉这些概念,您甚至可以使用ResponseEntity进一步自定义您的端点方法。

回答by Saver

As you see the "hit me", there's no mapping issue, but in your @RequestMapping annotation you specifie a produce type to "application/json" and you return a simple poor String not formatted and without any header('Content-Type: application/json').

当您看到“打我”时,没有映射问题,但是在您的 @RequestMapping 注释中,您将生产类型指定为“application/json”,并且您返回一个简单的、没有格式化且没有任何标头的糟糕字符串('Content-Type:应用程序/json')。

Add the header and format the outpout.

添加标头并格式化输出。

回答by Ghasem Sadeghi

When everything seems ok but receive 404, check this answer:

当一切正常但收到 404 时,请检查此答案:

As you know:
In the Spring MVC you can return view as a Stringor ModelAndViewobject.

如您所知:
在 Spring MVC 中,您可以将视图作为StringModelAndView对象返回。

IMPORTANT NOTE:
In both cases you have to pay attention to relative/absolute path:

重要说明:
在这两种情况下,您都必须注意相对/绝对路径

  1. If you declare /in the beginning of the view name, you are using absolute path.
    Namely it does not matter class level@RequestMappingand directly introduce itself as the final view name.
  2. If you do notdeclare /in the beginning of the view name, you are using relative path(relative to the class path) and therefore it appendsto the class level@RequestMappingto construct final view name.
  1. 如果/在视图名称的开头声明,则使用的是绝对路径
    类级别无关紧要@RequestMapping,直接介绍自己作为最终的视图名称
  2. 如果您没有/在视图名称的开头声明,则您使用的是相对路径(相对于类路径),因此它附加类级别@RequestMapping以构造最终视图名称

So, you have to consider the above notes when use the Spring MVC.

因此,在使用 Spring MVC 时,您必须考虑上述注意事项。

Example:
1. create two HTML file test1.htmland test2.htmlin the staticfolder of spring (boot) structure:
Please note that the class level@RequestMappingbehaves as a folderpath in the case of relativepath.

实施例:
1.创建两个HTML文件test1.htmltest2.htmlstatic弹簧(引导)结构的文件夹:
请注意,类水平@RequestMapping表现为一个文件夹中的情况下,路径的相对路径。

--- resources
    --- static
        --- classLevelPath     //behaves as a folder when we use relative path scenario in view names   
            --- test2.html      //this will be used for relative path [case (2)]
        --- test1.html          //this will be used for absolute path [case (1)]

  1. create a controller class like as the below. This example shows different cases with return Stringand ModelAndViewin both relativeand absolutepath.
  1. 创建一个如下所示的控制器类。这个例子显示了不同的情况与回报String,并ModelAndView在这两个相对绝对路径。

@Controller
@RequestMapping("/classLevelPath")
public class TestController {

    //case(1)
    @RequestMapping("/methodLevelAbsolutePath1")
    public String absolutePath1(Model model){
        //model.addAttribute();
        //...
        return "/test1.html";  
    }

    //case(1)
    @RequestMapping("/methodLevelAbsolutePath2")
    public ModelAndView absolutePath2(Model model){
        ModelAndView modelAndView = new ModelAndView("/test1.html");
        //modelAndView.addObject()
        //....
        return modelAndView; 
    }

    //case(2)
    @RequestMapping("/methodLevelRelativePath1")
    public String relativePath1(Model model){
        //model.addAttribute();
        //...
        return "test2.html";
    }

    //case(2)
    @RequestMapping("/methodLevelRelativePath2")
    public ModelAndView relativePath2(Model model){
        ModelAndView modelAndView = new ModelAndView("test2.html");
        //modelAndView.addObject()
        //....
        return modelAndView;  
    }


}

Note:
You can specify the suffix of your view files by a ViewResolver(for example InternalResourceViewResolveror spring.mvc.view.suffix=.htmlin the appliction.propertiesfile of Spring Boot and do not declare .htmlsuffix in the above code.

注意:
你可以通过a ViewResolver(例如InternalResourceViewResolver或者spring.mvc.view.suffix=.htmlappliction.propertiesSpring Boot的文件中)指定你的视图文件的后缀,不要.html在上面的代码中声明后缀。

Best Regard

最良好的问候