先来熟悉下,前端给后端传值的时候有哪几种方式呢?
HTML标签的form表单提交(GET、POST方式提交)Jquery中的ajax方式提交其他的一些如axios(其实就是封装了ajax) GET、POST区别那么说到了Form表单提交,有必要再去了解下,form表单中,提交方式get和post的区别,这里借用一下网上的图来说明一下。
一个HTTP请求,一般包含以下几个内容:
请求行(请求地址…)
请求头(头部信息…)
请求体(可存储数据)
请求空行(HTTP协议数据规范)
那么GET和POST提交方式的区别如上图所示:
在请求行中,POST方式不会把数据暴露出来,GET会暴露数据,但是GET方式处理数据的效率优于POST方式
,根据情况取舍POST方式会把数据处理好后,放入到请求体中
Content-Type
Content-Type,内容类型,一般是指网页中存在的Content-Type,用于定义网络文件的类型和网页的编码,决定文件接收方将以什么形式、什么编码读取这个文件 --百度百科
说白了,就是比如两个人要进行数据的传递,那么这两个人定义好一个内容类型
,一方以这种内容类型传递数据,另一方要遵守规定也以这种内容类型进行读取传输过来的数据。
Content-Type有哪些类型:(常见的)
application/x-www-form-urlencoded
: 标准表单编码类型
请求体中的数据会以普通表单形式(键值对)发送到后端
multipart/form-data
:类型
它会将请求体的数据处理为一条消息,以标签为单元,用分隔符分开。既可以上传键值对,也可以上传文件
application/json
: json类型
请求体中的数据会以json字符串的形式发送到后端
application/xml
: xml类型
Content-Type: application/json时
let params = {'title':'test', 'sub' : [1,2,3]}
axios({
method: 'post',
url: '/api/lockServer/search',
params
})
最终发送的请求是
{"title":"test","sub":[1,2,3]}
Content-Type: application/x-www-form-urlencoded 时
不设置Content-Type,使用URLSearchParams
const params = new URLSearchParams();
params.append('param1', 'value1');
params.append('param2', 'value2');
axios.post('/foo', params);
使用qs库编码数据(需要设置Content-Type)
import qs from 'qs';
const data = { 'bar': 123 };
const options = {
method: 'POST',
headers: { 'content-type': 'application/x-www-form-urlencoded' },
data: qs.stringify(data),
url,
};
axios(options);
Content-Type: multipart/form-data时
采用FormData方式
import axios from 'axios'
let data = new FormData();
data.append('code','1234');
data.append('name','yyyy');
axios.post(`${this.$url}/test/testRequest`,data)
.then(res=>{
console.log('res=>',res);
})
request的Content-Type
一般我们在开发的过程中需要注意客户端发送请求(Request)时的Content-Type设置,特别是使用ajax的时候,如果设置得不准确,很有可能导致请求失败。比如在spring中,如果接口使用了@RequestBody,spring强大的自动解析功能,会将请求实体的内容自动转换为Bean,但前提是请求的Content-Type必须设置为application/json
,否正就会返回415错误。
注:415 错误是 Unsupported media type,即不支持的媒体类型。
建议:
服务端响应(Response)的Content-Type最好也保持准确,虽然一般web开发中,前端解析响应的数据不会根据Content-Type,并且服务端一般能自动设置准确的Content-Type,但是如果乱设置某些情况下可能会有问题,比如导出文件,打开图片等。如果在spring项目里使用@ResponseBody,spring会将响应的Content-Type设置为application/json;charset=UTF-8
;,可能会导致文件无法导出,需要注意下。
建议:
一般情况下不需要显示设置;如果是文件导出,Content-Type 设置为 multipart/form-data,并且添加一个Content-Disposition设置为attachment;fileName=文件.后缀。(用springboot做过文件下载的应该比较熟悉这点)注:Content-Disposition是Content-Type的扩展,告诉浏览器d窗下载框,而不是直接在浏览器里展示文件。因为一般浏览器对于它能够处理的文件类型,如txt,pdf 等,它都是直接打开展示,而不是d窗下载框。
SpringBoot接收参数几种方式
进入正题。。
首先,学过springmvc应该知道,后端常用接收参数的几种方式有:
无注解 (普通类型、对象类型)
@RequestParam
@RequestBody
@PathVariable
HttpServletRequest
其中有一个小细节,可能大多数人都忽略了,那就是:
当使用注解方式+限制必传(默认的就是必传)
时,前端必须给我传这个参数,否则直接告诉他4xx(客户端错误),这个大家应该都知道。当使用无注解
和HttpServletRequest
时,如果前端没有把值传过来或者数据丢了,那么后端不会去报错,而是给一个默认值(普通类型(比如int类型默认0)和引用类型的默认值(null))
,继续执行代码。
先准备一个User类,方便后面使用
@Data
public class User {
private String name;
private String age;
}
// 普通类型
@GetMapping("/test1")
public void test1(String name, Integer age) {
System.out.println(name);
System.out.println(age);
}
// 对象类型
@GetMapping("/test2")
public void test2(User user) {
System.out.println(user);
}
普通类型
数据放入请求行
还不清楚请求行的,去上面看一下介绍就明白了。
控制台打印:
zs
21
数据放入请求体
控制台打印:
zs
21
对象类型
数据放入请求行
控制台打印:
User(name=zs, age=21)
数据放入请求体
控制台打印:
User(name=zs, age=21)
结论
无论是普通类型
还是对象类型
,放入请求行还是请求体,都能把数据读取出来。
使用@RequestParam注解时要注意,此注解一般使用在普通类型的属性上,因为对象类型的时候,你的值根本就不好传,当然像一些好传值的类型是可以用的,比如 List、数组…
@GetMapping("/test3")
public void test3(@RequestParam String name, @RequestParam String age) {
System.out.println(name);
System.out.println(age);
}
@GetMapping("/test4")
public void test3(@RequestParam List<Integer> ids) {
System.out.println(ids);
}
普通类型
放入请求行
控制台打印:
zs
21
放入请求体
控制台打印:
zs
21
对象类型
放入请求行
控制台打印:
[1, 2, 3]
放入请求体
控制台打印:
[1, 2, 3]
结论
使用@RequestParam注解时,和不使用注解一样,都可以接收到请求行
、请求体
中的数据。
但是要注意下,不使用注解时,不传值时会给属性默认值。
@RequestBody使用@RequestBody,后端接收Content-Type是application/json
类型的json数据,且数据都是放入请求体的
,Content-Type如果不对,则会报错,一般就是不支持Content-Type类型之类的,协商一下改一下就行。
@GetMapping("/test6")
public void test6(@RequestBody User user) {
System.out.println(user.toString());
}
@GetMapping("/test7")
public void test7(@RequestBody Map<String, Object> map) {
System.out.println(map.toString());
}
@GetMapping("/test8")
public void test8(@RequestBody List<Integer> ids) {
System.out.println(ids);
}
@GetMapping("/test9")
public void test9(@RequestBody int[] ids) {
System.out.println(ids);
}
test6(User类型)
请求体中的数据
控制台输出:
User(name=zs, age=21)
test7(Map类型)
控制台输出:
{name=zs, age=21}
test8(集合类型)
控制台打印:
[1, 2, 3]
这里一定是要注意的:
当我们接收的是集合或者数组的时候,前端传过来的一定不能是json对象,而是一个json数组,切记!!!
test9就不演示了,和test8是一模一样的,也是接收的json数组。
@PathVariable这种就是直接把参数值给拼接到url中,然后后端直接读取就可以了
当不传值时,由于url匹配不到,就直接404了
@GetMapping("/test5/{id}")
public void test5(@PathVariable Integer id) {
System.out.println(id);
}
控制台打印:
1
HttpServletRequest
接收的参数就是一个HttpServletRequest对象,然后从这个Request对象里取数据即可。
@GetMapping("/test10")
public void test10(HttpServletRequest request) {
String name = request.getParameter("name");
String age = request.getParameter("age");
String age2 = request.getParameter("age2");
System.out.println(name);
System.out.println(age);
System.out.println(age2);
}
请求行
控制台打印:
zs
21
null
请求体
控制台输出:
zs
21
null
结论:
和其他方式一样,都可以从请求行和请求体中读取到数据。数据没有传输过来那就采用默认值的方式。
如果请求行和请求体都传数据平时应该遇不到这样的问题,但是还是了解下吧,不然后面真遇到了,就直接蒙圈了。
请求行和请求体中传输的数据都是不同名的:
这种是没有任何问题的,相当于是我一些数据从请求行传过去,一些数据从请求体中传过去,能正常接收
请求行和请求体中传输的数据有同名的:
这种请求,我试了两个类型,其他的暂时没有试。如果是String类型的参数,那么它会先读取到请求体
中的数据,请求行
如果有同名的属性,那么会把值 拼接
到从请求体读取到的数据上,逗号分割。如zs,ls
如果是Integer类型,那么它只会以请求体中的数据为准
(同样是先读取请求体,然后如果请求行中有同名,直接过滤掉了–个人理解)
其他类型没有深究,有兴趣的可以去试试。如果后面遇到这种问题,这是一种排错的方式,仅供参考。
参考 Content-Type详解 Form表单的提交方式 SpringBoot 出现 Content type ‘application/x-www-form-urlencoded;charset=UTF-8’ not supported 前端axios配置Content-Type欢迎分享,转载请注明来源:内存溢出
评论列表(0条)