現在大多數互聯網項目都是采用前后端分離的方式開發,前端人員負責頁面展示和數據獲取,后端負責業務邏輯處理和接口封裝。當與前端交互的過程當中,常用json數據與前端進行交互,這樣想取出前端傳送過來的json數據的時候,就需要用到@RequestBody這個注解。@RequestBody注解用於讀取http請求的內容(字符串),通過springmvc提供的HttpMessageConverter接口將讀到的內容轉換為json、xml等格式的數據並綁定到controller方法的參數上。
提交方式為 POST 時,
JQuery Ajax 以 application/x-www-form-urlencoded 上傳 JSON對象 ,
后端用 @RequestParam 或者Servlet 獲取參數。
JQuery Ajax 以 application/json 上傳 JSON字符串,
后端用 @RquestBody 獲取參數。
獲取參數的幾種常用注解
@PathVariable:一般我們使用URI template樣式映射使用,即url/{param}這種形式,也就是一般我們使用的GET,DELETE,PUT方法會使用到的,我們可以獲取URL后所跟的參數。
@RequestParam:一般我們使用該注解來獲取多個參數,在()內寫入需要獲取參數的參數名即可,一般在PUT,POST中比較常用。
@RequestBody:該注解和@RequestParam殊途同歸,我們使用該注解將所有參數轉換,在代碼部分在一個個取出來,也是目前我使用到最多的注解來獲取參數
還有@RequestHeader來獲取頭信息里的值,@CookieValue來獲取Cookie值等等。在這,我也僅僅說明一些較常用的取值方法而已。
一.請求路徑參數
get請求
一般用於查詢數據,采用明文進行傳輸,一般用來獲取一些無關用戶信息的數據,
@GetMapping 組合注解,是 @RequestMapping(method = RequestMethod.GET) 的縮寫
1.get請求,url路徑傳參
get請求一般通過url傳參,如:
http://localhost:4001/api/unit?code=111
后端要獲取code參數,可以使用@RequestParam注解
-
@RestController
-
public
class HelloController {
-
@RequestMapping(value="/hello",method= RequestMethod.GET)
-
public String sayHello(@RequestParam Integer id){
-
return
"id:"+id;
-
}
-
}
2.get請求,url路徑參數
如:http://localhost:4001/api/unit/1
后端使用@PathVariable可以接收路徑參數1。
-
@RestController
-
public
class HelloController {
-
@RequestMapping(value="/hello/{id}/{name}",method= RequestMethod.GET)
-
public String sayHello(@PathVariable("id") Integer id,@PathVariable("name") String name){
-
return
"id:"+id+
" name:"+name;
-
}
-
}
小結:當請求為get請求時,使用@PathVariable或者@RequestParam獲取參數值,獲取路徑參數。@PathVariable一般用於獲取獲取url/{id}這種形式的參數;@RequestParam獲取查詢參數。即url?name=這種形式
二、Body參數
POST請求
1、post請求,Body傳值
較推薦使用json格式傳值,postman設置如圖:
后端接受這種數據應該采用@RequestBody或者@requestparam
-
//map接收
-
@PostMapping(path = "/demo1")
-
public void demo1(@RequestBody Map<String, String> person) {
-
System.out.println(person.get(
"name"));
-
}
-
-
//或者是實體對象接收
-
@PostMapping(path = "/demo1")
-
public void demo1(@RequestBody Person person) {
-
System.out.println(person.toString());
-
}
注意;@RequestBody,它是用來處理前台定義發來的數據Content-Type: 而不是application/x-www-form-urlencoded編碼的內容,例如application/json, application/xml等;使用@RequestBody注解接收參數的時候,從名稱上來看也就是說要讀取的數據在請求體里,前台的Content-Type必須要改為application/json,所以要發post請求,因為Ajax使用的POST,並且發送的是JSON對象。前端必須指定請求json數據的contentType為:application/json,否則會報類型不支持的異常錯誤“org.springframework.web.HttpMediaTypeNotSupportedException”
當Ajax以application/x-www-form-urlencoded格式上傳即使用JSON對象,后台只能使用@RequestParam 或者Servlet獲取參數。 當Ajax以application/json格式上傳即使用JSON字符串,后台可以使用@RquestBody或者@RequestParam獲取。
如何定義后台接收參數“能映射上去”呢?若是json中的key在實體中都能找到對應的field,自動映射,也就是說:前台傳入的json中的key在實體中必須要存在,不然就會報錯
第三類:請求頭參數以及Cookie
post請求,Headers、cookie傳值
在這里我們把Content-Type設置為了json格式。
我們還可以在headers里面加入別的參數,比如Token。
后端可以通過HttpServletRequest 獲取請求頭的內容,如:
-
request.getHeader(string name)方法:String
-
request.getHeaders(String name)方法:Enumeration
-
request.getHeaderNames()方法
-
-
@GetMapping("/demo3")
-
public void demo3(HttpServletRequest request) {
-
System.out.println(request.getHeader(
"myHeader"));
-
for (Cookie cookie : request.getCookies()) {
-
if (
"myCookie".equals(cookie.getName())) {
-
System.out.println(cookie.getValue());
-
}
-
}
-
}
四、HttpServletRequest
前端js發送ajax請求,Content-Type發送信息至服務器時內容編碼類型,默認是( application/x-www-form-urlencoded 這種格式的特點就是,name/value 成為一組,每組之間用 & 聯接,這種形式是沒有辦法將復雜的 JSON 組織成鍵值對形式),
data_type設置你收到服務器數據的格式,不指定自動判斷
-
var jsonObj = {
"openid":
"xxx",
"username":
"Ed sheeran",
"password":
"123"};
-
/*
-
Jquery默認Content-Type為application/x-www-form-urlencoded類型
-
*/
-
$.ajax({
-
type:
'POST',
-
url:
"/login",
-
dataType:
"json",
-
data: JSON.stringify(jsonObj),
-
success: function(data) {
-
console.log(data)
-
},
-
error: function() {
-
console.log(
"fucking error")
-
}
-
});
后端Servlet接受參數。前端報 200,后端報 返回值都是null
-
@Controller
-
public
class LoginController {
-
@PostMapping("/login")
-
public void login(HttpServletRequest request){
-
System.err.println(request.getParameter(
"openid"));
-
System.err.println(request.getParameter(
"username"));
-
System.err.println(request.getParameter(
"password"));
-
}
后端改 @RequestBody 接受參數。前端報 415,后端報 Content type ‘application/x-www-form-urlencoded;charset=UTF-8’ not supported
Http status 415 Unsupported Media Type
-
@Controller
-
public
class LoginController {
-
@PostMapping("/login")
-
public void login(@RequestBody Map<String,Object> map){
-
System.err.println(map.get(
"username"));
-
System.err.println(map.get(
"password"));
-
System.err.println(map.get(
"openid"));
-
}
前端加 contentType : “application/json”。前端報 200,后端能接受到參數
-
var jsonObj = {
"openid":
"xxx",
"username":
"Ed sheeran",
"password":
"123"};
-
$.ajax({
-
type:
'POST',
-
url:
"/login",
-
dataType:
"json",
-
data: JSON.stringify(jsonObj),
-
contentType :
"application/json",
-
success: function(data) {
-
console.log(data)
-
},
-
error: function() {
-
console.log(
"fucking error")
-
}
-
});
-
@Controller
-
public
class LoginController {
-
@PostMapping("/login")
-
public void login(@RequestBody Map<String,Object> map){
-
System.err.println(map.get(
"username"));
-
System.err.println(map.get(
"password"));
-
System.err.println(map.get(
"openid"));
-
}
-
}
后端使用對象來獲取參數。前端報 200,后端 也ok@Controller
-
public
class LoginController {
-
@PostMapping("/login")
-
public void login(@RequestBody Form form){
-
System.err.println(form);
-
}
-
}
-
public
class Form {
-
private String openid;
-
private String username;
-
private String password;
-
-
// get set
-
-
@Override
-
public String toString() {
-
return
"Form{" +
-
"openid='" + openid +
'\'' +
-
", username='" + username +
'\'' +
-
", password='" + password +
'\'' +
-
'}';
-
}
-
}
四、參數校檢
1.后端接收到前端的數據,如果想對前端的數據進行校驗,可以加入springboot的Validate 功能依賴包
-
<dependency>
-
<groupId>org.hibernate
</groupId>
-
<artifactId>hibernate-validator
</artifactId>
-
</dependency>
使用只需要在接收數據的實體上加上@Valid注解,BindingResult接收錯誤的不合法的提示信息
接收參數的實體的屬性上還需要加校驗的注解@NotEmpty(message="密碼不能為空")
-
還可以使用正則表達式對屬性進行校驗。只需要加入以下注解即可:
-
@Pattern(
-
regexp = 正則表達式,
-
message = "輸入格式不合法"
-
)
2、當后端接收完前端的數據,響應一般也是返回json數據給前端,此時只需要在后端控制器Contoller類加上@ResponseBody即可。該注解用於將Controller的方法返回的對象,通過HttpMessageConverter接口轉換為指定格式的數據如:json,xml等,通過Response響應給客戶端。@Controller 與 @ResponseBody 結合使用返回json數據給前端,我們還可以使用@RestController替換他們,從而使代碼更加的精簡
注意:
接收到的參數默認都是字符串類型的
有的注解只能用在String類型的屬性上
@JsonProperty可以實現前端的屬性名和后台實體類的屬性名不一致問題
校驗方式:
使用@RequestBody @Valid 對JSON參數進行獲取和校驗
最終選擇交互方式
前端 application/json,post請求,上傳 josn字符串, 后端結合@RequestBody 使用自定義對象 或者 Map接收參數,這是最常用的方法
前端代碼
-
var jsonObj = {
"openid":
"xxx",
"username":
"Ed sheeran",
"password":
"123"};
-
/*
-
Jquery默認Content-Type為application/x-www-form-urlencoded類型
-
*/
-
$.ajax({
-
type:
'POST',
-
url:
"/login",
-
dataType:
"json",
-
data: JSON.stringify(jsonObj),
-
contentType :
"application/json",
-
success: function(data) {
-
console.log(data)
-
},
-
error: function() {
-
console.log(
"fucking error")
-
}
-
});
后端代碼1
-
@Controller
-
public
class LoginController {
-
@PostMapping("/login")
-
public void login(@RequestBody Form form){
-
System.err.println(form);
-
}
-
}
后端代碼2
-
@Controller
-
public
class LoginController {
-
@PostMapping("/login")
-
public void login(@RequestBody Map<String,Object> map){
-
System.err.println(map.get(
"username"));
-
System.err.println(map.get(
"password"));
-
System.err.println(map.get(
"openid"));
-
}
-
}
如果是get請求,結合 @RequestParam 或者@PathVariable獲取路徑參數
如果是通過header傳值,使用HttpServletRequest獲取
如果是post請求body傳參,對於參數較多的,可以使用對象或者map結合@RequestBody使用接收參數,如果是少量參數,可以使用@RequestParam單個映射接收。
參考文獻
AJAX POST請求中參數以form data和request payload形式在servlet中的獲取方式