《知识点扫盲 · 请求类型 ContentType》

CSDN 2024-08-25 14:33:01 阅读 95

📢 大家好,我是 【战神刘玉栋】,有10多年的研发经验,致力于前后端技术栈的知识沉淀和传播。 💗

🌻 CSDN入驻不久,希望大家多多支持,后续会继续提升文章质量,绝不滥竽充数,欢迎多多交流。👍

文章目录

写在前面的话常见的 Content-Type 接收application/jsonapplication/x-www-form-urlencodedmultipart/form-datatext/plainapplication/xml

实战运用类型不匹配的情况Axios 针对不同 ContentType

总结陈词

CSDN.gif

写在前面的话

<code>Content-Type是HTTP头部的一部分,用于指示发送到HTTP请求或响应中的数据的格式和类型。在 SpringMVC 开发中,当处理HTTP请求时,Content-Type 非常重要,因为它告诉Spring如何解析请求体中的数据,以及如何设置响应的格式。

举个例子,打开谷歌浏览器,按F12打开开发者工具,此时访问某网站,可以在开发者工具查找接口调用情况。如下所示,查看任意请求,基本都可以看到请求头和响应头包含 Content-Type

先关注一下请求头的Content-Type,客户端发送请求的请求头里面的 Content-Type 告诉服务提供方如何解析和处理请求或响应中的数据,不同的 Content-Type 值对应不同的数据格式,服务器和客户端可以根据这个信息进行相应的处理。

image.png

本篇博文主要介绍一下 SpringMVC 开发中,针对客户端发起的不同请求类型,后端控制器参数部分应当如何处理。


常见的 Content-Type 接收

在 Spring MVC 开发中,常见的 Content-Type 值及其对应的接收方式如下:

application/json

**类型描述:**表示请求体是 JSON 格式的数据。

**接收方式:**使用 @RequestBody 注解来接收 JSON 数据,Spring 会自动将 JSON 转换为 Java 对象。

**参考源码:**RequestResponseBodyMethodProcessor

**补充说明:**日常开发中,这种方式应该使用较多。

<code>@PostMapping(value = "/api/user", consumes = "application/json")

public ResponseEntity<User> createUser(@RequestBody User user) { -- -->

}

application/x-www-form-urlencoded

**类型描述:**表示请求体是表单数据,通常用于表单提交,如果在 HTTP 请求中没有显式设置 Content-Type,那么默认的 Content-Type 通常是此种格式。

**接收方式:**使用 @RequestParam 注解来接收单个参数,本质是 request.getParameterValues。

**使用场景:**这种格式通常用于 HTML 表单的提交,适合简单的数据传输。

**数据格式:**在这种格式下,表单数据会被编码为键值对的形式,多个键值对之间用 & 符号连接,键和值之间用 = 符号分隔。例如:name=John&age=30&city=NewYork

**参考源码:**RequestParamMethodArgumentResolver

@PostMapping(value = "/api/user", consumes = "application/x-www-form-urlencoded")

public ResponseEntity<User> createUser(@RequestParam String userName) {

}

Tips:也可以使用 @ModelAttribute 注解来接收整个表单数据并映射到 Java 对象。

multipart/form-data

**类型描述:**表示请求体包含文件上传和表单数据。用于文件上传场景,可以上传文件和其他表单数据。

**接收方式:**使用 MultipartFile 类型来接收上传的文件。

@PostMapping(value = "/api/upload", consumes = "multipart/form-data")

public ResponseEntity<String> uploadFile(@RequestParam("file") MultipartFile file) {

// 处理文件

}

Tips:常用于文件上传,但也可以使用 @RequestParam 注解接收文件和其他表单字段。

text/plain

描述:表示请求体是纯文本格式的数据。

接收:使用 @RequestBody 注解来接收文本数据。

application/xml

描述:表示请求体是 XML 格式的数据。

接收:使用 @RequestBody 注解来接收 XML 数据,Spring 会自动将 XML 转换为 Java 对象。

实战运用

类型不匹配的情况

当客户端(Postman)传递的请求类型是 application/x-www-form-urlencoded,但是依然用请求体方式传递参数,服务端用 @RequestBody 方式接收会怎么样?

如下图所示:

image.png

这个错误是入参解析器抛出的,SpringMVC 会根据注解找到 RequestResponseBodyMethodProcessor 用来处理入参,当执行到 readWithMessageConverters 方法的时候,会发现遍历所有参数转换器,都找不到可以处理这个请求类型的参数转换器,直接抛出异常了。

image.png

【扩展说明】

大部分情况,SpringMVC 提供了相应的方法接收,但请求参数可能千奇百怪,框架不可能帮我们面面俱到。

针对一些复杂的参数类型,建议自定义参数解析器或参数转换器,封装便捷的解决方案,造福开发人员。


Axios 针对不同 ContentType

这边以前端常用的请求插件 Axios 为例,介绍一下不同 ContentType 的场景下需要。

Axios 是一个非常流行的 JavaScript 库,基于 Promise 实现,用于在浏览器和 Node.js 环境中进行 HTTP 请求,详细可参考这篇博文《程序猿入职必会(7) · 前端请求工具封装》,这边不展开介绍了。

application/json

这是最常用的内容类型之一,表示请求体是 JSON 格式。

参数直接传递 JSON 对象格式即可,Axios 会自动将对象转换为 JSON 字符串。

<code>import axios from 'axios';

const data = { -- -->

name: '战神',

age: 28

};

axios.post('https://example.com/api/user', data, {

headers: {

'Content-Type': 'application/json'

}

});

application/x-www-form-urlencoded

这种类型用于发送表单数据,数据以键值对的形式编码在请求体中。

使用 qs.stringify 将对象转换为 URL 编码的字符串,再进行请求。

注意,这种方式,Axios 不会自动帮忙转换,要手动处理。

import axios from 'axios';

import qs from 'qs';

const data = {

name: '战神',

age: 28

};

axios.post('https://example.com/api/user', qs.stringify(data), {

headers: {

'Content-Type': 'application/x-www-form-urlencoded'

}

})

// 也可以使用这种方式

const params = new URLSearchParams();

params.append('name', 'John');

params.append('age', '30');

multipart/form-data

这种类型通常用于文件上传,数据以多部分形式编码在请求体中。

使用 FormData 对象来构建请求体,不需要手动设置 Content-Type,Axios 会自动处理。

import axios from 'axios';

const formData = new FormData();

formData.append('file', fileInput.files[0]);

axios.post('https://example.com/api/upload', formData, {

headers: {

'Content-Type': 'multipart/form-data'

}

})

源码扩展说明

大多数情况,Content-Type 也可以不显示的指定,Axios 会根据参数的类型自动设置相应的 Content-Type。

可以参考 Axios 的部分源码如下,比如判断参数符合isURLSearchParams格式,则直接设置form请求类型。

// transformRequest

if (utils$1.isURLSearchParams(data)) {

headers.setContentType('application/x-www-form-urlencoded;charset=utf-8', false);

return data.toString();

}

var isFileList;

if (isObjectPayload) {

if (contentType.indexOf('application/x-www-form-urlencoded') > -1) {

return toURLEncodedForm(data, this.formSerializer).toString();

}

if ((isFileList = utils$1.isFileList(data)) || contentType.indexOf('multipart/form-data') > -1) {

var _FormData = this.env && this.env.FormData;

return toFormData(isFileList ? {

'files[]': data

} : data, _FormData && new _FormData(), this.formSerializer);

}

}

if (isObjectPayload || hasJSONContentType) {

headers.setContentType('application/json', false);

return stringifySafely(data);

}

但还是建议加上,让自己的代码可读性更高。

总结一下

根据不同的 Content-Type,构造请求体的方式会有所不同。

在发送 JSON 数据时,Axios 会自动处理序列化。对于 application/x-www-form-urlencoded,需要使用 qs 库进行处理。对于文件上传,使用 FormData 对象。

在设置请求头时,确保 Content-Type 与请求体的格式相匹配。


总结陈词

此篇文章针对Content-Type进行了知识扫码,仅供学习参考。

Content-Type 的不同值决定了如何接收和处理请求体中的数据,开发者需要根据实际需求选择合适的 Content-Type 和接收方式,以确保数据能够正确解析和处理。

💗 后续会逐步分享企业实际开发中的实战经验,有需要交流的可以联系博主。

CSDN_END.gif



声明

本文内容仅代表作者观点,或转载于其他网站,本站不以此文作为商业用途
如有涉及侵权,请联系本站进行删除
转载本站原创文章,请注明来源及作者。