Spring MVC - 为什么不能一起使用@RequestBody和@RequestParam

abh*_*123 56 post spring spring-mvc http-post http-request-parameters

使用带有Post请求的HTTP dev客户端和Content-Type application/x-www-form-urlencoded

1)只有@RequestBody

请求 - localhost:8080/SpringMVC/welcome In Body - name = abc

码-

@RequestMapping(method = RequestMethod.POST)
public String printWelcome(@RequestBody String body, Model model) {
    model.addAttribute("message", body);
    return "hello";
}
Run Code Online (Sandbox Code Playgroud)

//按预期将body标记为"name = abc"

2)只有@RequestParam

请求 - localhost:8080/SpringMVC/welcome In Body - name = abc

码-

@RequestMapping(method = RequestMethod.POST)
public String printWelcome(@RequestParam String name, Model model) {
    model.addAttribute("name", name);
    return "hello";
}
Run Code Online (Sandbox Code Playgroud)

//按预期将名称命名为"abc"

3)两者在一起

请求 - localhost:8080/SpringMVC/welcome In Body - name = abc

码-

@RequestMapping(method = RequestMethod.POST)
public String printWelcome(@RequestBody String body, @RequestParam String name, Model model) {
    model.addAttribute("name", name);
    model.addAttribute("message", body);
    return "hello";
}
Run Code Online (Sandbox Code Playgroud)

// HTTP错误代码400 - 客户端发送的请求在语法上不正确.

4)上面的params位置改变了

请求 - localhost:8080/SpringMVC/welcome In Body - name = abc

码-

@RequestMapping(method = RequestMethod.POST)
public String printWelcome(@RequestParam String name, @RequestBody String body, Model model) {
    model.addAttribute("name", name);
    model.addAttribute("message", body);
    return "hello";
}
Run Code Online (Sandbox Code Playgroud)

//没有错误 名字是'abc'.身体是空的

5)一起但获取类型url参数

请求 - localhost:8080/SpringMVC/welcome?name = xyz In Body - name = abc

码-

@RequestMapping(method = RequestMethod.POST)
public String printWelcome(@RequestBody String body, @RequestParam String name, Model model) {
    model.addAttribute("name", name);
    model.addAttribute("message", body);
    return "hello";
}
Run Code Online (Sandbox Code Playgroud)

//名称是'xyz',正文是'name = abc'

6)与5)相同,但参数位置已更改

代码 -

@RequestMapping(method = RequestMethod.POST)
public String printWelcome(@RequestParam String name, @RequestBody String body, Model model) {
    model.addAttribute("name", name);
    model.addAttribute("message", body);
    return "hello";
}
Run Code Online (Sandbox Code Playgroud)

// name ='xyz,abc'正文为空

有人可以解释这种行为吗?

Sot*_*lis 46

@RequestBodyjavadoc的状态

指示方法参数的注释应绑定到Web请求的主体.

它使用已注册的实例HttpMessageConverter将请求主体反序列化为带注释的参数类型的对象.

@RequestParam

注释,指示应将方法参数绑定到Web请求参数.

  1. Spring将请求的主体绑定到带注释的参数@RequestBody.

  2. Spring将请求主体(url编码的参数)中的请求参数绑定到方法参数.Spring将使用参数的名称,即.name,映射参数.

  3. 参数按顺序解析.首先@RequestBody处理.春天将消耗所有HttpServletRequest InputStream.然后当它尝试解析时@RequestParam,默认情况下required,查询字符串中没有请求参数或请求体的剩余部分,即.没有.所以它失败了,因为处理程序方法无法正确处理请求.

  4. @RequestParam行为的处理程序首先,读取它可以HttpServletRequest InputStream映射请求参数的内容,即.整个查询字符串/ url编码的参数.它这样做并获取abc映射到参数的值name.当@RequestBody运行处理程序时,请求正文中没有任何内容,因此使用的参数是空字符串.

  5. @RequestBody读取正文的处理程序并将其绑定到参数.然后,处理程序@RequestParam可以从URL查询字符串中获取请求参数.

  6. @RequestParam从body和URL查询String读取的处理程序.它通常会将它们放在a中Map,但由于参数是类型的String,因此Spring将序列Map化为逗号分隔值.@RequestBody那时的处理程序再没有什么可以从正文中读取.

  • @ abhihello123如果你有**很多耐心.下载源jar并在发送请求时使用调试器并逐步执行代码.你想看的类是`RequestParamMethodArgumentResolver`,它处理`@RequestParam`. (2认同)

Ram*_*rna 6

回答这个问题为时已晚,但它可以帮助新读者,似乎是版本问题。我跑了所有这些测试弹簧4.1.4和发现的顺序@RequestBody,并@RequestParam没有关系。

  1. 和你的结果一样
  2. 和你的结果一样
  3. 给了body= "name=abc",并且name = "abc"
  4. 与 3 相同。
  5. body ="name=abc", name = "xyz,abc"
  6. 与 5 相同。