Spring MVC-为什么不能同时使用@RequestBody和@RequestParam
将HTTP开发客户端与Post请求和内容类型application/x-www-form-urlencoded一起使用 1) 仅@RequestBody URL:localhost:8080/SpringMVC/welcomeSpring MVC-为什么不能同时使用@RequestBody和@RequestParam,spring,spring-mvc,post,http-post,http-request-parameters,Spring,Spring Mvc,Post,Http Post,Http Request Parameters,将HTTP开发客户端与Post请求和内容类型application/x-www-form-urlencoded一起使用 1) 仅@RequestBody URL:localhost:8080/SpringMVC/welcome Body:name=abc @RequestMapping(method = RequestMethod.POST) public String printWelcome(@RequestBody String body, Model model) { model
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
@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.
@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
@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'
2) 仅@RequestParam
URL:localhost:8080/SpringMVC/welcome在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) 一起
URL:localhost:8080/SpringMVC/welcomeBody: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
@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.
@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
@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'
4) 以上参数位置已更改
URL:localhost:8080/SpringMVC/welcomeBody: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
@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.
@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
@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'
5) 一起获取类型url参数
URL:localhost:8080/SpringMVC/welcome?name=xyzBody: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
@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.
@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
@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)相同,但参数位置已更改
有人能解释这种行为吗?javadoc声明
@RequestBody
指示方法参数的注释应绑定到主体
web请求的一部分
它使用HttpMessageConverter
的注册实例将请求正文反序列化为带注释参数类型的对象
以及@RequestParam
javadoc状态
指示方法参数应绑定到的注释
web请求参数
@RequestBody
注释的参数name
,来映射参数@RequestBody
。Spring将使用所有的HttpServletRequest
InputStream
。然后,当它尝试解析默认情况下所需的@RequestParam
时,查询字符串中没有请求参数或请求正文中剩余的内容,即没有。因此,使用400失败,因为处理程序方法无法正确处理请求@RequestParam
的处理程序首先执行操作,读取HttpServletRequest
InputStream
的内容,以映射请求参数,即整个查询字符串/url编码参数。它这样做,并获取映射到参数名称的值abc
。当@RequestBody
的处理程序运行时,请求正文中没有任何内容,因此使用的参数是空字符串
@RequestBody
的处理程序读取主体并将其绑定到参数。@RequestParam
的处理程序随后可以从URL查询字符串中获取请求参数@RequestParam
的处理程序同时读取主体和URL查询字符串。它通常将它们放在映射中
,但由于参数的类型为字符串
,因此Spring将映射
序列化为逗号分隔的值。然后,@RequestBody
的处理程序再次没有任何内容可从主体中读取您还可以将@RequestParam default required状态更改为false,这样就不会生成HTTP响应状态代码400。这将允许您按自己喜欢的顺序放置注释
@RequestParam(required = false)String name
这是因为Servlet规范不是很直截了当。如果您使用的是本机
HttpServletRequest
实现,则无法同时获取URL编码正文和参数。Spring做了一些变通,这使得它更加奇怪和不透明
在这种情况下,Spring(版本3.2.4)使用getParameterMap()
方法中的数据为您重新呈现一个实体。它混合了GET和POST参数,并打破了参数顺序。导致混乱的类是ServletServerHttpRequest
。不幸的是,它不能被替换,但是类StringHttpMessageConverter
可以被替换
不幸的是,清洁的解决方案并不简单:
StringHttpMessageConverter
。复制/覆盖原始类调整方法readInternal()
HttpServletRequest
覆盖getInputStream()
,getReader()
和getParameter*()
方法 if (inputMessage instanceof ServletServerHttpRequest) {
ServletServerHttpRequest oo = (ServletServerHttpRequest)inputMessage;
input = oo.getServletRequest().getInputStream();
} else {
input = inputMessage.getBody();
}
然后必须在上下文中注册转换器
<mvc:annotation-driven>
<mvc:message-converters register-defaults="true/false">
<bean class="my-new-converter-class"/>
</mvc:message-converters>
</mvc:annotation-driven>
这里描述了第二步:现在回答这个问题已经太迟了,但它可以帮助新读者, 似乎是版本问题。我用Spring4.1.4运行了所有这些测试,发现
@RequestBody
和@RequestParam
的顺序并不重要
body=“name=abc”
,以及name=“abc”
body=“name=abc”
,name=“xyz,abc”
假设在案例4)中,帖子主体是
name=abc&age=2
,那么根据您的解释,名称应该是abc
,主体应该是&age=2
,但实际结果是name是abc
,主体是空的。@abhihello123它读取整个url编码的表单参数。所以整个name=abc&age=2
。但是如果我再加一个@RequestParam,它会把2放入age。这意味着这个名字只能读abc。很抱歉安装了窃听器。@abhihello123是的,在这种情况下,已读取完整的查询字符串,可以从中生成下一个@RequestParam
。参数存储在一个映射中,每次都可以检查请求参数。@abhihello123,如果您有足够的耐心的话。下载源JAR并在发送请求和逐步完成代码时使用调试器。您要查看的类是RequestParamMethodArgumentResolver
,它处理@RequestParam
。是的,响应状态代码400不会是g