先上代码,再说区别:
前端:
使用@RequestParam:主要处理contentType为application/x-www-form-urlencoded的数据(默认)
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script type="text/javascript" src="/js/jquery-3.3.1.js"></script>
</head>
<body>
<input id="username" name="username"/>
<input type="password" id="password" name="password"/>
<input type="checkbox" id="rememberMe" name="rememberMe"/>
<button type="button">提交</button>
</body>
<script type="text/javascript">
var obj = window.document.location;
var BASE_PATH = obj.href.substring(0, obj.href.indexOf(obj.pathname));
$("button").on("click", function () {
var dataForm = {};
var username = $("#username").val();
var password = $("#password").val();
dataForm.username = username;
dataForm.password = password;
$.ajax({
url: BASE_PATH + "/test",
type: "post",
data:dataForm,
success: function f(data) {
}
})
});
</script>
</html>
使用@ResponseBody:主要处理contentType不为application/x-www-form-urlencoded的数据
在ajax中要指明contentType:"application/json;charset=UTF-8",data:JSON.stringify(json数组);
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script type="text/javascript" src="/js/jquery-3.3.1.js"></script>
</head>
<body>
<input id="username" name="username"/>
<input type="password" id="password" name="password"/>
<input type="checkbox" id="rememberMe" name="rememberMe"/>
<button type="button">提交</button>
</body>
<script type="text/javascript">
var obj = window.document.location;
var BASE_PATH = obj.href.substring(0, obj.href.indexOf(obj.pathname));
$("button").on("click", function () {
var dataForm = {};
var username = $("#username").val();
var password = $("#password").val();
dataForm.username = username;
dataForm.password = password;
$.ajax({
url: BASE_PATH + "/test",
type: "post",
contentType : "application/json;charset=UTF-8",
data:JSON.stringify(dataForm),
success: function f(data) {
}
})
});
</script>
</html>
后端:
使用@RequestParam:要指明前端传过来的参数名并与其对应
@PostMapping("test")
public Object test(@RequestParam (value = "username") String username,
@RequestParam (value = "password") String password){
System.out.println(username);
System.out.println(password);
return null;
}
使用@RequestBody:直接对象接收,属性名要与前端传过来的数据的key值对应
package com.example.demo.vo;
/**
* @author FastKing
* @version 1.0
* @date 2018/10/10 13:54
**/
public class TestVO {
private String username;
private String password;
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
}
@PostMapping("test")
public Object test(@RequestBody TestVO testVO){
System.out.println(testVO.getUsername());
System.out.println(testVO.getPassword());
return null;
}
按F12看一下Network里对应请求:
使用@RequestParam:Content-Type为application/x-www-form-urlencoded,参数在FormData中
使用@RequestBody:Content-Type为application/json,参数在Request PayLoad中
因为两个注解处理的数据的编码格式不同,ajax又不可能同时指定两个编码格式,所以一般情况下是不可以同时使用的;
如果一定要同时使用,在请求头上拼@RequestParam接收的参数,使用@RequestBody的那一套前端把对象传到后端,后端就能获取到了
上面已经讲了,可以使用多个@RequestParam获取数据,那么可以使用多个@RequestBody吗,现在上代码试一下:
前端:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script type="text/javascript" src="/js/jquery-3.3.1.js"></script>
</head>
<body>
<input id="username" name="username"/>
<input type="password" id="password" name="password"/>
<input type="checkbox" id="rememberMe" name="rememberMe"/>
<button type="button">提交</button>
</body>
<script type="text/javascript">
var obj = window.document.location;
var BASE_PATH = obj.href.substring(0, obj.href.indexOf(obj.pathname));
$("button").on("click", function () {
var dataForm = {};
var username = $("#username").val();
var password = $("#password").val();
dataForm.username = username;
dataForm.password = password;
dataForm.usernameTwo = "rootTwo";
dataForm.passwordTwo = "123456Two";
$.ajax({
url: BASE_PATH + "/test",
type: "post",
contentType : "application/json;charset=UTF-8",
data:JSON.stringify(dataForm),
success: function f(data) {
}
})
});
</script>
</html>
后端:
VO类
package com.example.demo.vo;
/**
* @author FastKing
* @version 1.0
* @date 2018/10/10 17:53
**/
public class TestTwoVO {
private String usernameTwo;
private String passwordTwo;
public String getUsernameTwo() {
return usernameTwo;
}
public void setUsernameTwo(String usernameTwo) {
this.usernameTwo = usernameTwo;
}
public String getPasswordTwo() {
return passwordTwo;
}
public void setPasswordTwo(String passwordTwo) {
this.passwordTwo = passwordTwo;
}
}
Controller
@PostMapping("test")
public Object test(@RequestBody TestVO testVO, @RequestBody TestTwoVO testTwoVO) {
System.out.println(testVO.getUsername());
System.out.println(testVO.getPassword());
System.out.println(testTwoVO.getUsernameTwo());
System.out.println(testTwoVO.getPasswordTwo());
return null;
}
会报如下错误:
WARN 26532 --- [nio-8080-exec-1] .w.s.m.s.DefaultHandlerExceptionResolver : Failed to read HTTP message: org.springframework.http.converter.HttpMessageNotReadableException: I/O error while reading input message; nested exception is java.io.IOException: Stream closed
由于前端往后端传数据是以IO流的方式,而第一个@RequestBody在接收完自己的数据后,就把IO流关掉了,导致第二个@RequestBody无法再读取上一个IO流,所以@RequestBody不能在同一个方法中出现多次