如何使用@RequestBody调用@RestController?

时间:2016-12-01 12:12:40

标签: java spring servlets spring-web

我有一个简单的servlet如下:

@RestController
public class TestServlet {
    @RequestMapping(value = "/test1")
    public String test1() {
        return "test1";
    }

    @RequestMapping(value = "/test2")
    public String test2(@RequestBody TestClass req) {
        return "test2";
    }

    public static class TestClass {
        private String value;

        public String getValue() {
            return value;
        }

        public void setValue(String value) {
            this.value = value;
        }
    }
}

但只有没有接收参数的servlet才能正常工作:

作品:http://localhost:8080/test1

不起作用:http://localhost:8080/test2?value=1234

  

org.springframework.http.converter.HttpMessageNotReadableException:   缺少必需的请求正文:public java.lang.String

为什么@RequestBody注释不起作用?我错过了一件重要的作品吗?

4 个答案:

答案 0 :(得分:4)

@Controller和@RestController之间的一个区别是你不必编写@RequestBody和@ResponseBody,这意味着你的控制器方法中没有注释的任何参数(比如@PathVariable, @ModelAttribute ....)将隐式具有@RequestBody,因此必须作为HTTP实体主体进行POST。所以你需要发送JSON / XML作为POST的一部分。你所做的是作为URL的一部分发送数据,这使得它成为请求参数而不是正文数据,你需要@RequestParam来从URL中提取数据。

另外,我建议你使用@ GetMapping / @ PostMapping或在@RequestMapping注释中包含method参数,你不太可能想要一个服务用于POST和GET,所以你应该是在控制器方法描述中尽可能具体,以限制错误情况。

答案 1 :(得分:2)

第二个URL不起作用的原因是因为在使用@RequestBody时,您发送到端点的数据需要通过请求标头中的data属性来完成。将?attr=value附加到正在params标题中发送属性的网址时。

有两种方法可以解决这个问题:

  1. 将您的端点更改为以下内容:

    public String test2(@RequestParam("value") TestClass req) { //Endpoint code }

  2. 将您的端点更改为以下内容:

    @RequestMapping(value="test2",method=RequestMethod.POST) public String test2(@RequestBody TestClass req){ //Endpoint code }

    并使您的通话类似于此(例如angularjs):

    http.post({url:/*url*/,data:/*object to send*/});

  3. 第二个选项很可能就是你想要的东西,因为它看起来你正在尝试将json对象发送到你的端点,我相信你只能通过发出POST请求而不是GET请求来做到这一点< / p>

答案 2 :(得分:0)

请忽略@RequestBody注释,因为这仅适用于POST次请求。

  public String test2(@Valid TestClass req) {
        return "test2";
    }

答案 3 :(得分:0)

当您将控制器方法参数声明为@RequestBody时,您希望它从请求正文中恢复,而不是作为常规&#34; http参数。

您可以尝试使用任何类型的Firefox(RESTClient)或Chrome(PostMan)插件,并尝试使用其中一个。你也可以使用SoapUI来做到这一点。

请求应该是POST以这种方式请求的网址:

POST http://localhost:8080/test2

您必须提供能够提供预期Content-TypeAccept的http标头。如果使用Json,请将它们设置为:

Content-Type: application/json
Accept: text/html (As your method returns only a String)

然后将param写入请求正文。如果在Json中,就像这样:

{
"value":"the provided value"
}