前端发送的数据到后端时到底经历了什么? ---- 表单数据提交
关于post请求, 可以首先参见: 博客
1 Content-Type对各种请求的影响
(1) get请求:
GET 请求不存在请求实体部分,键值对参数放置在 URL 尾部,浏览器把form数据转换成一个字串(name1=value1&name2=value2...),然后把这个字串追加到url后面,用?分割,加载这个新的url。因此请求头不需要设置 Content-Type 字段
但是, 非 ASCII 码会自动进行编码转换,例如发送请求:www.bilibili.com?hehe=你的我的, 中文部分会被转换成ASCII编码
(2) post请求:
1.application/x-www-form-urlencoded:数据被编码为名称/值对。这是标准的编码格式。默认行为。会将表单内的数据转换拼接成 key-value 对(非 ASCII 码进行编码)
2.multipart/form-data(一般用来上传文件): 数据被编码为一条消息,页上的每个控件对应消息中的一个部分, 如果是想要文件的上传操作, 就必须要使用这个请求头
3.application/json: 数据被编码为json格式的字符串, 以json格式的字符串发送给后端
3.text/plain: 数据以纯文本形式(text/json/xml/html)进行编码,其中不含任何控件或格式字符。postman软件里标的是RAW。(中文不进行编码)
说明: 其实, 请求头类型的设定, 就是为了制定一个规范, 然后, 整个领域都按照这个规范进行工作,
不管是哪一种请求头, 起到的作用就是, 首先将数据处理成与此请求头对应的数据格式, 然后将数据交送给后端并告诉后端我交付的数据到底是哪一种格式,
最为重要的一点是: 前端发送过来的数据, 一定要按照请求头中的数据对请求数据进行编码, 否则, 后端是无法正确获取到请求数据的, 这也是之前一直搞不明白问题所在的主要原因
真正处理数据的, 其实是后端, 后端需要识别请求头的类型(即请求数据的类型), 然后根据不同的类型解析不同的数据, 这才是最主要的,
不过, 现在的一些框架, 好像都已经封装好了对请求头的识别, 我们只需要按照具体的使用方法就可以直接获取需要前端传送过来的请求内容
2 springboot中对各种不同请求头的请求中的参数获取
(1) application/x-www-form-urlencoded: 直接通过RequestParam(value="name")获取即可
(2) multipart/form-data: 这个也可以直接通过RequestParam(value="name")的形式获取, 不过, 需要注意的是, 请求的数据, 一定要按照此种类型进行编码, 下面会具体针对这个东西进行一些问题的解决
(3) application/json: 这个可以通过RequestBody Map<String, Object> map的形式获取, 不过, 需要注意的, 传送的数据, 一定要被序列化成json格式, 可以手动序列化( JSON.stringify() ), 也可以借助一些封装好的框架进行序列化(好像axios就会自动进行一些序列化, 具体还不清楚)
3 几个注意点:
(1) 如果想要进行文件上传操作, 就必须要使用multipart/form-data请求头, 方式有两种
一种是通过form标签, 设置enctype="multipart/form-data", 这样在表单提交的时候, 就会自动将所有的数据编码成multipart/form-data格式
另一种是构建FormData对象, 然后将FormData对象作为数据传送给后端, 由于FormData对象默认会使得Content-Type变为multipart/form-data, 所以, 也会自动将数据编码成multipart/form-data格式
(2) jquery中封装的ajax请求, 有两个参数需要特别注意
processData: 这个参数是jquery中特有的, 默认情况下, 会将数据处理成application/x-www-form-urlencoded格式, 所以, 如果我们进行文件上传操作时(即需要设置请求头为multipart/form-data时), 需要将属性值设置为false, 即禁用这个选项
contentType: 这个参数是用来设置请求头的, 也可以在header:{...}属性中进行设置, 同样, 如果我们是想要进行文件上传操作, 也需要将这个属性设置为false, 即禁用这个属性, 因为, 它的属性值默认为application/x-www-form-urlencoded, 那, 为什么不将其设置为multipart/form-data呢? 因为, 对于multipart/form-data格式, 请求头需要有两个属性, 即除了设置multipart/form-data, 还需要附加一个属性boundary=---fjdkgjgdjakdjgjdgajl, 但是这个值一般都是由浏览器随机生成并指定的, 无法手动定义(如果手动定义的话会出错), 所以, 就需要禁用contentType属性了, 禁用之后, 会使用FormData对象中的post方式作为contentType, 即是multipart/form-data喽, 并且浏览器还会自动生成boundary, 不是很好吗.