1. 程式人生 > >@RequestBody和@RequestParam的區別

@RequestBody和@RequestParam的區別

先上程式碼,再說區別:

前端:

使用@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不能在同一個方法中出現多次