A summary of the posture of Spring’s RequestBody

There are several different ways to handle request parameters in SpringMVC, such as the following ones that are common to us

  • According to theHttpServletRequestObject to obtain
  • According to the@PathVariableThe annotation gets url parameters
  • According to the@RequestParamThe annotation gets the request parameters
  • Gets the request parameters according to the Bean
  • According to the@ModelAttributeThe annotation gets the request parameters

Interested in all of these ways can check out this blog post: SpringMVC’s Approach to getting request Parameters

In addition to the above methods, there is also a way to use @requestBody, and this article focuses on how to use it and what to do about it

I. Use posture

1. Service interface

With the Spring framework, @RequestBody is easy to use. It’s easy to write a case using @RequestBody

@Slf4j
@RestController
public class ReqBodyController {
    @Data
    @NoArgsConstructor
    @AllArgsConstructor
    public static class Req {
        private String key;
        private Integer size;
    }

    @RequestMapping(value = "/body", method = {RequestMethod.POST, RequestMethod.GET, RequestMethod.OPTIONS})
    public BaseRsp body(@RequestBody Req req) {
        log.info("req: {}", req);
        return newBaseRsp<>(req); }}Copy the code

@requsetparam @requsetbody @requsetparam @requsetbody @requsetparam @requsetparam @requsetbody @requsetparam @requsetparam @requsetbody @requsetparam

@Target({ElementType.PARAMETER})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface RequestBody {
    // The default argument must exist, otherwise an exception will be thrown
    boolean required(a) default true; 
}
Copy the code

This is not a problem for the backend, but how to use it (specifically for the front end).

2. Interface invocation

Before you use the RequestBody annotation, it’s important to understand the context in which the RequestBody annotation is used (in other words, how it is different from RequestParam, and why it should be created separately).

RequestBody

RequestBody annotations are used to handle content-type coded content that is not the default application/ X-wwW-form-urlcoded content, such as application/ JSON or application/ XML. It is generally used to handle the Application/JSON type.

A. the content-type definition

Before we move on to the next step, it’s worth explaining what the Content-type HTTP header is for

MediaType: Internet MediaType: Internet MediaType. Also known as MIME Type, content-type is used in Http protocol headers to represent the media Type in a specific request.

Common media formats are as follows:

  • Text/HTML: indicates the HTML format
  • Text /plain: Indicates the plain text format
  • Text/XML: indicates the XML format
  • Image/GIF: Indicates the GIF image format
  • Image/JPEG: JPG image format
  • Image/PNG: The image format is PNG

Media format types beginning with Application:

  • Application/XHTML + XML: Indicates the XHTML format
  • Application/XML: indicates the XML data format
  • Application/Atom + XML: Atom XML aggregation format
  • Application /json: Indicates the JSON data format
  • Application/PDF: PDF format
  • Application/Msword: Document format
  • Application /octet-stream: binary stream data (such as common file downloads)
  • Application/X-wwW-form-urlencoded: Default encType, form data will be coded as key/value format and sent to the server

B. Content-type Example

The above is the basic definition and value, the following combined with examples of typical ways to explain

  • Application/X-www-form-urlencoded: Data is coded as name/value pairs. This is the standard encoding format.
  • Multipart /form-data: Data is encoded as a message, and each control on the page corresponds to a part of the message.
  • Text /plain: Data is encoded in the form of text/json/ XML/HTML without any controls or format characters

For front-end use, the encType attribute of a form is encoded in two ways: Application/X-www-form-urlencoded and multipart/form-data, default is Application/X-www-form-urlencoded.

A Get request

When a Get request is initiated, the browser uses Application/X-wwW-form-urlencoded, converts the form data into a string (key1=value1&key2=value2…) To the URL, which is what we often see when a URL has a request parameter

Post form

When a post request is initiated, if no file is transmitted, the browser will also encapsulate the data of the form form into the result of K = V and throw it into the HTTP body. Take the form submitted by the blog of open Source China as an example. In a typical POST form, the uploaded data is assembled in the form data with kv structure

If there is a file transfer scenario, the content-type Type will be upgraded to multipart/form-data. This section will not be expanded in detail

Post json string

In addition to the previous method of post form, there is another common one, that is, all the form data is put in a big JSON string, and then thrown to the back end, here is also an online instance, an e-commerce platform goods published, the screenshot is as follows

Note that Request Payload is a large JSON string

C. RequestBody request

According to the RequestBody definition, accessing the previously defined interface is not possible using traditional form passing. The curl command tests the following

curl -X POST -d 'key=haha&size=123' http://127.0.0.1:19533/body
Copy the code

1, Content type ‘application/x-www-form-urlencoded ‘; 2, Content type ‘application/x-www-form-urlencoded ‘; 3, Content type ‘application/ x-wwW-form-urlencoded ‘; 4, Content type ‘application/ x-wwW-form-urlencoded ‘; charset=UTF-8’

Therefore, the gesture needs to be displayed to add the request header, and the pass parameter is changed

curl -l -H "Content-type: application/json" -X GET -d '{"key": "! 23", "size": 10}' http://127.0.0.1:19533/body
Copy the code

The result is as follows

3. Precautions

A. Content-type Displays the specified content

You can see how the @RequestBody annotation is used, In this way, the REST interface no longer receives requests whose content-type is Application/X-www-form-urlencoded, but needs to display requests specified as Application/JSON

B. Request method

Does RequestBody support GET methods? So what happens if we change it to GET?

Curl Test Mode

curl -l -H "Content-type: application/json" -X GET -d '{"key": "! 23", "size": 10}' http://127.0.0.1:19533/body\?key\=app
Copy the code

The screenshot of the corresponding back-end debug is as follows. It is found that there is no problem when the GET mode is used, and parameters can still be obtained

Let’s switch to the famous POSTMAN

When using the POST method, the screenshot is shown below. The main thing is to change the content-type of the header and then add the JSON string format to the body

However, when you change it to GET, the body is completely blacked out, meaning it does not support submitting the body data on a GET request

Url Request Mode

Next, switch to the URL request mode and see if get requests are directly supported

{http://127.0.0.1:19533/body?"key": ! "" 23"."size"10} :Copy the code

When you enter a request in the browser, the server 400 is changed to curl, and you throw a RequestBody exception because there is no RequestBody.

summary

  • When using RequestBody to get parameters, it’s better to use the POST method, but it’s better to follow the crowd

C. Obtain parameters

HttpServletRequest = RequestBody; HttpServletRequest = RequestBody; RequestBody = RequestBody

The request url for

curl -l -H "Content-type: application/json" -X POST -d '{"key": "! 23", "size": 10}' http://127.0.0.1:19533/body\?url\=ddd
Copy the code

The following is the screenshot of the corresponding debug. The URL parameter is available, but the RequestBody parameter is not

First of all, the following paragraph of analysis, did not look at the source code, purely in the personal inference, if there is a problem, to be misled to apologize for the friend, also hope to understand the friend, a lot of criticism

Starting from the idea of file transfer, when the front end transfers files to the back end, the back end writes the uploaded binary stream to 'MultipartFile' in a stream-based way. After the binary stream is read, RequestBody cannot be read again. First, the body parameter is read from the HttpServletRequest Reader stream and is wrapped into the req object above, unlike the URL parameter. Write back to ` javax.mail. Servlet. ServletRequest# getParameterMap `Copy the code

To do a little verification of the above guess, get the request body parameter directly from the HttpServletRequest Reader stream

@RequestMapping(value = "/body", method = {RequestMethod.POST, RequestMethod.GET, RequestMethod.OPTIONS})
public BaseRsp body(HttpServletRequest request) throws IOException {
    BufferedReader reader = request.getReader();
    StringBuilder builder = new StringBuilder();
    String line = reader.readLine();
    while(line ! =null) {
        builder.append(line);
        line = reader.readLine();
    }
    reader.close();

    String reqBody = builder.toString();
    Req req = JSON.parseObject(reqBody, Req.class);
    log.info("req: {}, request: {}", req, request.getParameterMap());
    return new BaseRsp<>(req);
}
Copy the code

Verify the following

In fact, there is an interesting place that has aroused my curiosity, and that is how the HttpServletRequest thing works in the Spring container. I will talk about it later.

4. Summary

  • The ReuqestBody is primarily a request parameter in the form of a JSON string, requiring the user to specify the headercontent-type:application/json
  • RequestBody typically requires the caller to use a POST request
  • The RequsetBody parameter is not placed in the HttpServletRequest Map and therefore cannot passjavax.servlet.ServletRequest#getParameterTo obtain

II. The other

Reference 0.

  • How to obtain SpringMVC request parameters
  • Http content-type description

1. A gray Blog: https://liuyueyi.github.io/hexblog.

A gray personal blog, record all study and work in the blog, welcome everyone to visit

2. Statement

The letter is not as good as the book, has been on the content, purely a statement, due to the limited personal ability, there are inevitably omissions and mistakes, such as found bugs or better suggestions, welcome criticism and correction, not grudging gratitude

  • Micro-blog address: small gray Blog
  • QQ: A gray /3302797840

3. Scan for attention

Small gray Blog& public account

Knowledge of the planet