前情介绍:

请求参数涉及前后端,前端如何编码,后端如何解码。具体来说,前端涉及:请求方式、请求方式使用场景、请求参数编码、表单参数编码,springboot后端涉及:请求解码、请求参数注入。当你有条理的理清这些东西,就能得心用手的使用和长久的记忆。
参考文档1
参考文档2

请求方式:

  1. 常用的请求方式:get请求方式、post请求方式。
  2. 那么选择一个请求方式意味着什么呢?第一、决定了HTTP报文中的method字段,第二、决定了HTTP报文是否有请求体,get方式决定了请求参数直接跟url拼接,没有请求体,而post方式决定了你的请求参数放在请求体中。注意,以上东西就是教科书上介绍的东西,但是请求参数是怎么组织然后以什么样的格式放在url或请求体中的呢?这就是有请求参数编码决定的。也就是说:协议并没有规定数据必须使用什么编码方式,开发者完全可以自己决定请求主体的格式,只要最后发送的 HTTP 请求满足上面的格式就可以。

    请求参数编码:

  3. 常见的请求参数编码有三种:

application/x-www-form-urlencoded
multipart/form-data
application/json
它们决定了HTTP报文中Content-Type请求头是什么

  1. 当选择了一个请求参数编码,又意味着什么呢?如上所述,决定了请求参数是以什么样的格式组织在一起然后放在url中或请求体中。
  2. 当选择了application/x-www-form-urlencoded:

它主要做了两件事:第一、组织请求参数为以下格式:
title=test&sub%5B%5D=1&sub%5B%5D=2&sub%5B%5D=3
第二、对中文进行了url编码,每个中文汉字转换成了%xx形式

  1. 当选择了multipart/form-data:

这是文件提交时用到的编码方式,请求参数被组装成以下格式:即多段传输格式
———WebKitFormBoundaryrGKCBY7qhFd3TrwA
Content-Disposition: form-data; name=”text”

title
———WebKitFormBoundaryrGKCBY7qhFd3TrwA
Content-Disposition: form-data; name=”file”; filename=”chrome.png”
Content-Type: image/png

PNG … content of chrome.png …
———WebKitFormBoundaryrGKCBY7qhFd3TrwA—

  1. 当选择了application/json:

组织格式:就是json字符串的形式
{“title”:”test”,”sub”:[1,2,3]}

请求方式使用场景:

这是一种什么概念呢?上述既讲了请求方式,又讲了请求参数编码,一种请求方式,能对应不同的请求参数编码方式,那么在不同的使用场景下,它们是如何搭配的呢?

  1. 首先是针对get请求方式:要明白get请求方式始终使用的是application/x-www-form-urlencoded编码,

即便指定编码方式,也不起作用,或者说get请求方式跟Content-Type没有关系,Content-Type只是决定了请求体中的内容编码方式。也就是说,get方式请求时,url和请求参数总是以下的格式:
http://localhost:8080/ajaxGet?id=1&username=%5B%5D&userTrueName=%5B%5D%6C

具体使用场景:

  1. 1. 地址栏直接使用
  2. 1. <a>链接
  3. 1. form表单提交,method指定为get
  4. 1. Ajax请求,type指定为get

$.ajax({
type: “GET”,
url: “http://localhost:8080/ajaxGet“,
data:{“id”:1,”username”:”用户名”,”userTrueName”:”真实名称”}
});

  1. 针对post请求方式:它可以与上述三种编码方式任意搭配:
    1. 设置了Content-Type为:application/x-www-form-urlencoded:

这应该是最常见的 POST 提交数据的方式了。浏览器的原生

表单,如果不设置 enctype 属性,那么最终就会以 application/x-www-form-urlencoded 方式提交数据
POST http://www.example.com HTTP/1.1
Content-Type: application/x-www-form-urlencoded;charset=utf-8

title=test&sub%5B%5D=1&sub%5B%5D=2&sub%5B%5D=3

  1. 2. 设置了Content-Type为:application/json

POST http://www.example.com HTTP/1.1
Content-Type: application/json;charset=utf-8

{“title”:”test”,”sub”:[1,2,3]}

  1. 3. 设置了Content-Type为:multipart/form-data

POST http://www.example.com HTTP/1.1
Content-Type:multipart/form-data; boundary=——WebKitFormBoundaryrGKCBY7qhFd3TrwA

———WebKitFormBoundaryrGKCBY7qhFd3TrwA
Content-Disposition: form-data; name=”text”

title
———WebKitFormBoundaryrGKCBY7qhFd3TrwA
Content-Disposition: form-data; name=”file”; filename=”chrome.png”
Content-Type: image/png

PNG … content of chrome.png …
———WebKitFormBoundaryrGKCBY7qhFd3TrwA—

具体使用场景:

  1. 1. form表单提交
  2. 1. Ajax请求

表单参数编码enctype:

上述讲了get方式、post方式都可以用在form表单中,只需指定method属性即可。表单参数编码enctype和请求参数编码Content-Type的区别是什么呢?
第一、表单参数编码是form标签的一个属性,只用在表单中,并且enctype 默认以”application/x-www-form-urlencoded”对表单数据进行编码,而Content-Type是HTTP报文的一个请求体,表明请求体的编码类型(这不就与get方式无关了)
第二、form表单中的enctype属性的值会作为Content-Type的值写入HTTP报文中,因此指定了enctype也就指定了Content-Type,默认值是application/x-www-form-urlencoded。这说明了什么呢?不就是当使用场景是表单提交时(无论是get方式还是post方式),enctype和Content-Type就是一回事了。

以下是表单提交的过程:
1、识别出表单中表单元素的有效项,作为提交项
2、构建一个表单数据集
3、根据form表单中的enctype属性的值作为content-type对数据进行编码
4、根据form表单中的action属性和method属性向指定的地址发送数据

springboot后端请求参数解码:

上述已经说了浏览器编码数据的同时将对应的编码方式写入了Content-Type,那么为什么指定这个HTTP字段呢?因为服务器可以通过这个字段解码请求参数。

springboot后端请求参数注入:

这里从请求参数编码方式Content-Type角度说明前端编码方式不同时,后端springboot处理方法注入的方式也不同。

  1. 当Content-Type选择了application/x-www-form-urlencoded或multipart/form-data时,后端注入方式一致:
    1. 实体类接收
    2. Map接收,必须使用@RequestParam注解
    3. 拆开单个参数接收(参数少的情况可使用)
    4. 后台的file文件需要使用MultipartFile类型接收
  2. 当Content-Type选择了application/json时,即传输的Json是json字符串,必须使用@RequestBody注解,
    1. 字符串接收,然后对Json字符串解析转换
    2. 实体类接收
    3. Map接收

如:

  1. @PostMapping(value = "ajaxPost")
  2. public void ajaxPost(@RequestBody String param){
  3. JSONObject json = JSON.parseObject(param);
  4. }
  5. @PostMapping(value = "ajaxPost")
  6. public void ajaxPost(@RequestBody User user){
  7. }
  8. @PostMapping(value = "ajaxPost")
  9. public void ajaxPost(@RequestBody Map map){
  10. }