Spring MVC - 为什么不能一起使用@RequestBody 和@RequestParam [英] Spring MVC - Why not able to use @RequestBody and @RequestParam together

查看:66
本文介绍了Spring MVC - 为什么不能一起使用@RequestBody 和@RequestParam的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

使用带有 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.

  1. 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屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆