@RequestBody 和 @RequestParam 有啥区别?

Posted

技术标签:

【中文标题】@RequestBody 和 @RequestParam 有啥区别?【英文标题】:What is difference between @RequestBody and @RequestParam?@RequestBody 和 @RequestParam 有什么区别? 【发布时间】:2015-03-18 08:22:04 【问题描述】:

我通过Spring文档了解@RequestBody,他们给出了以下解释:

@RequestBody方法参数注解表示方法参数应该绑定到HTTP请求体的值。例如:

@RequestMapping(value = "/something", method = RequestMethod.PUT)
public void handle(@RequestBody String body, Writer writer) throws IOException 
  writer.write(body);

您可以使用HttpMessageConverter 将请求正文转换为方法参数。 HttpMessageConverter负责将HTTP请求消息转换为对象,将对象转换为HTTP响应体。

DispatcherServlet 支持使用DefaultAnnotationHandlerMappingAnnotationMethodHandlerAdapter 进行基于注释的处理。在 Spring 3.0 中,AnnotationMethodHandlerAdapter 扩展为支持@RequestBody,并且默认注册了以下HttpMessageConverters:

...

但我的困惑是他们在文档中写的那句话是

@RequestBody 方法参数注解表示方法参数应该绑定到 HTTP 请求体的值。

这是什么意思?谁能给我一个例子?

spring doc中@RequestParam的定义是

表示方法参数应绑定到 Web 请求参数的注解。支持 ServletPortlet 环境中的带注释的处理程序方法。

我对他们感到困惑。请帮我举个例子说明它们之间的不同之处。

【问题讨论】:

learning Spring's @RequestBody and @RequestParam 的可能重复项 @kryger 。这不是重复的,因为我有我的研究,我已经通过了春季文档。我已经要求提供示例。我已经给你定义了。我想举例说明它们之间有什么不同。上面的问题没有提供足够的解释,所以我认为它不应该被否决。 【参考方案1】:

@RequestParam 带注释的参数链接到特定的 Servlet 请求参数。参数值被转换为声明的方法参数类型。 此注解表示方法参数应绑定到 Web 请求参数。

例如,对 Spring RequestParam(s) 的 Angular 请求如下所示:

$http.post('http://localhost:7777/scan/l/register?username="Johny"&password="123123"&auth=true')
      .success(function (data, status, headers, config) 
                        ...
                    )

带有 RequestParam 的端点:

@RequestMapping(method = RequestMethod.POST, value = "/register")
public Map<String, String> register(Model uiModel,
                                    @RequestParam String username,
                                    @RequestParam String password,
                                    @RequestParam boolean auth,
                                    HttpServletRequest httpServletRequest) ...

@RequestBody 带注释的参数链接到 HTTP 请求正文。使用 HttpMessageConverters 将参数值转换为声明的方法参数类型。 此注解表示方法参数应绑定到 Web 请求的正文。

例如,对 Spring RequestBody 的 Angular 请求如下所示:

$scope.user = 
            username: "foo",
            auth: true,
            password: "bar"
        ;    
$http.post('http://localhost:7777/scan/l/register', $scope.user).
                        success(function (data, status, headers, config) 
                            ...
                        )

带有 RequestBody 的端点:

@RequestMapping(method = RequestMethod.POST, produces = "application/json", 
                value = "/register")
public Map<String, String> register(Model uiModel,
                                    @RequestBody User user,
                                    HttpServletRequest httpServletRequest) ... 

希望这会有所帮助。

【讨论】:

【参考方案2】:

映射HTTP请求头Content-Type,处理请求体。

@RequestParamapplication/x-www-form-urlencoded,

@RequestBodyapplication/json,

@RequestPartmultipart/form-data,


RequestParam (Spring Framework 5.1.9.RELEASE API)

映射到查询参数、表单数据和多部分请求中的部分。

RequestParam 可能与名称-值表单字段一起使用

RequestBody (Spring Framework 5.1.9.RELEASE API)

绑定到 Web 请求的正文。请求的主体通过 HttpMessageConverter 传递,以根据请求的content type 解析方法参数。 (例如 JSON、XML)

RequestPart (Spring Framework 5.1.9.RELEASE API)

用于关联“multipart/form-data”请求的部分

RequestPart 可能用于包含更复杂内容的部分

HttpMessageConverter (Spring Framework 5.1.9.RELEASE API)

一个可以在 HTTP 请求和响应之间进行转换的转换器。

所有已知的实现类:...、AbstractJsonHttpMessageConverter、AbstractXmlHttpMessageConverter、...

【讨论】:

准确回答!不同的注解映射到不同的Web请求数据形式,由其“Content-Type”标头表示。【参考方案3】:

@RequestParam 使 Spring 将请求参数从 GET/POST 请求映射到您的方法参数。

GET 请求

http://testwebaddress.com/getInformation.do?city=Sydney&country=Australia

public String getCountryFactors(@RequestParam(value = "city") String city, 
                    @RequestParam(value = "country") String country) 

POST 请求

@RequestBody 使 Spring 将整个请求映射到模型类,然后您可以从那里检索或设置其 getter 和 setter 方法的值。检查下面。

http://testwebaddress.com/getInformation.do

您有来自前端的 JSON 数据并命中您的控制器类


   "city": "Sydney",
   "country": "Australia"

Java 代码 - 后端 (@RequestBody)

public String getCountryFactors(@RequestBody Country countryFacts)
    
        countryFacts.getCity();
        countryFacts.getCountry();
    


public class Country 

    private String city;
    private String country;

    public String getCity() 
        return city;
    

    public void setCity(String city) 
        this.city = city;
    

    public String getCountry() 
        return country;
    

    public void setCountry(String country) 
        this.country = country;
    

【讨论】:

【参考方案4】:

@RequestParam 注释告诉 Spring 它应该将请求参数从 GET/POST 请求映射到您的方法参数。例如:

请求:

GET: http://someserver.org/path?name=John&surname=Smith

端点代码:

public User getUser(@RequestParam(value = "name") String name, 
                    @RequestParam(value = "surname") String surname) 
    ...  
    

所以基本上,虽然@RequestBody 将整个用户请求(甚至对于 POST)映射到一个字符串变量,@RequestParam 使用一个(或多个 - 但更复杂的)请求参数到您的方法参数。

【讨论】:

请举例说明.@RequestBody【参考方案5】:

这很简单,只要看看他们的名字@RequestParam 它由两部分组成,一个是“Request”,这意味着它将处理请求,另一部分是“Param”,它本身是有意义的,它只会映射对 java 对象的请求参数。 @RequestBody 的情况也是如此,它将处理随请求到达的数据,例如客户端是否发送了带有请求的 json 对象或 xml,此时必须使用 @requestbody。

【讨论】:

【参考方案6】:

这里以@RequestBody为例,先看控制器!!

  public ResponseEntity<Void> postNewProductDto(@RequestBody NewProductDto newProductDto) 

   ...
        productService.registerProductDto(newProductDto);
        return new ResponseEntity<>(HttpStatus.CREATED);
   ....


这里是角度控制器

function postNewProductDto() 
                var url = "/admin/products/newItem";
                $http.post(url, vm.newProductDto).then(function () 
                            //other things go here...
                            vm.newProductMessage = "Product successful registered";
                        
                        ,
                        function (errResponse) 
                            //handling errors ....
                        
                );
            

简单看一下表格

 <label>Name: </label>
 <input ng-model="vm.newProductDto.name" />

<label>Price </label> 
 <input ng-model="vm.newProductDto.price"/>

 <label>Quantity </label>
  <input ng-model="vm.newProductDto.quantity"/>

 <label>Image </label>
 <input ng-model="vm.newProductDto.photo"/>

 <Button ng-click="vm.postNewProductDto()" >Insert Item</Button>

 <label > vm.newProductMessage </label>

【讨论】:

以上是关于@RequestBody 和 @RequestParam 有啥区别?的主要内容,如果未能解决你的问题,请参考以下文章

@RequestBody 和 @RequestParam 有啥区别?

结合@PathVariable 和@RequestBody

@RequestBody 和 @GetMapping 不能同时使用

@RequestBody 和 @GetMapping 不能同时使用

@PathVariable注解和@RequestBody注解

Spring中的@RequestBody和@ResponseBody注解