Spring MVC - 为什么不能一起使用@RequestBody 和@RequestParam [英] Spring MVC - Why not able to use @RequestBody and @RequestParam together
问题描述
使用带有 Post 请求和 Content-Type application/x-www-form-urlencoded 的 HTTP 开发客户端
Using HTTP dev client with Post request and Content-Type application/x-www-form-urlencoded
网址:本地主机:8080/SpringMVC/welcome
正文:name=abc
URL: localhost:8080/SpringMVC/welcome
Body: name=abc
@RequestMapping(method = RequestMethod.POST)
public String printWelcome(@RequestBody String body, Model model) {
model.addAttribute("message", body);
return "hello";
}
// Gives body as 'name=abc' as expected
2) 只有@RequestParam
网址:本地主机:8080/SpringMVC/welcome
在正文中 - name=abc
2) Only @RequestParam
URL: 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";
}
// Gives name as 'abc' as expected
3) 两者一起
网址:本地主机:8080/SpringMVC/welcome
正文:name=abc
3) Both together
URL: localhost:8080/SpringMVC/welcome
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";
}
// HTTP Error Code 400 - The request sent by the client was syntactically incorrect.
4) 上面的参数位置改变了
网址:本地主机:8080/SpringMVC/welcome
正文:name=abc
4) Above with params position changed
URL: localhost:8080/SpringMVC/welcome
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";
}
// No Error. Name is 'abc'. body is empty
5) 一起但获取类型 url 参数
网址:localhost:8080/SpringMVC/welcome?name=xyz
正文:name=abc
5) Together but get type url parameters
URL: localhost:8080/SpringMVC/welcome?name=xyz
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";
}
// name is 'xyz' and body is '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";
}
// name = 'xyz,abc' body is empty
有人可以解释这种行为吗?
Can someone explain this behaviour?
推荐答案
@RequestBody
javadoc 说明
The @RequestBody
javadoc states
指示方法参数应该绑定到主体的注解的网络请求.
Annotation indicating a method parameter should be bound to the body of the web request.
它使用 HttpMessageConverter
的注册实例将请求正文反序列化为带注释的参数类型的对象.
It uses registered instances of HttpMessageConverter
to deserialize the request body into an object of the annotated parameter type.
和 @RequestParam
javadoc 状态
And the @RequestParam
javadoc states
表明方法参数应该绑定到的注解一个网络请求参数.
Annotation which indicates that a method parameter should be bound to a web request parameter.
Spring 将请求的主体绑定到使用
@RequestBody
注释的参数上.
Spring 将请求主体中的请求参数(url 编码的参数)绑定到您的方法参数.Spring 将使用参数的名称,即.name
,映射参数.
Spring binds request parameters from the request body (url-encoded parameters) to your method parameter. Spring will use the name of the parameter, ie. name
, to map the parameter.
参数按顺序解析.@RequestBody
首先被处理.Spring 将消耗所有的 HttpServletRequest
InputStream
.当它尝试解析 @RequestParam
(默认情况下为 required
)时,查询字符串中没有请求参数或请求正文的剩余部分,即.没有.所以它以 400 失败,因为处理程序方法无法正确处理请求.
Parameters are resolved in order. The @RequestBody
is processed first. Spring will consume all the HttpServletRequest
InputStream
. When it then tries to resolve the @RequestParam
, which is by default required
, there is no request parameter in the query string or what remains of the request body, ie. nothing. So it fails with 400 because the request can't be correctly handled by the handler method.
@RequestParam
的处理程序首先采取行动,读取 HttpServletRequest
InputStream
的所有内容以映射请求参数,即.整个查询字符串/url 编码的参数.它这样做并获取映射到参数 name
的值 abc
.当 @RequestBody
的处理程序运行时,请求正文中没有任何内容,因此使用的参数是空字符串.
The handler for @RequestParam
acts first, reading what it can of the HttpServletRequest
InputStream
to map the request parameter, ie. the whole query string/url-encoded parameters. It does so and gets the value abc
mapped to the parameter name
. When the handler for @RequestBody
runs, there's nothing left in the request body, so the argument used is the empty string.
@RequestBody
的处理程序读取正文并将其绑定到参数.@RequestParam
的处理程序然后可以从 URL 查询字符串中获取请求参数.
The handler for @RequestBody
reads the body and binds it to the parameter. The handler for @RequestParam
can then get the request parameter from the URL query string.
@RequestParam
的处理程序从正文和 URL 查询字符串中读取.它通常会将它们放在 Map
中,但由于参数是 String
类型,Spring 会将 Map
序列化为逗号分隔值.@RequestBody
的处理程序然后再次从正文中读取任何内容.
The handler for @RequestParam
reads from both the body and the URL query String. It would usually put them in a Map
, but since the parameter is of type String
, Spring will serialize the Map
as comma separated values. The handler for @RequestBody
then, again, has nothing left to read from the body.
这篇关于Spring MVC - 为什么不能一起使用@RequestBody 和@RequestParam的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!