前後端資料互動形式隨手筆記

卡牌300發表於2024-05-09

註解@RequestParam Map<String, String> params 的使用

1 在Spring MVC中,使用@RequestParam Map<String, String> params可以接收前端發出的請求引數並將它們作為一個Map收集起來。這種方式非常靈活,可以處理來自前端的各種資料提交形式。以下是一些常見的前端資料傳送方式,它們都可以被@RequestParam Map<String, String> params成功接收和處理:

1. 查詢字串(Query String)

這是最常見的GET請求資料傳輸方式。例如:

GET /endpoint?param1=value1&param2=value2

在這種情況下,Map將包含鍵值對"param1" -> "value1""param2" -> "value2"

2. 表單資料(Form Data)

當使用POST請求提交表單資料時(Content-Type: application/x-www-form-urlencoded),例如:

POST /endpoint
Content-Type: application/x-www-form-urlencoded

param1=value1&param2=value2

@RequestParam Map<String, String> params同樣可以捕獲這些引數並將它們存入Map

3. AJAX請求

使用JavaScript發出的AJAX請求,無論是GET還是POST(當Content-Type被設定為application/x-www-form-urlencoded),傳送的查詢字串或表單資料都可以被接收。例如,使用jQuery的$.ajax方法:

$.ajax({
url: '/endpoint',
method: 'POST',
contentType: 'application/x-www-form-urlencoded',
data: {
param1: 'value1',
param2: 'value2'
}
});

注意事項

  • 當使用@RequestParam Map<String, String> params時,所有請求引數都會被包含在Map中,但這種方法僅限於接收簡單的鍵值對,並不適用於複雜結構如JSON物件或XML。

  • 對於JSON型別的資料(Content-Type: application/json),你不能使用@RequestParam Map<String, String> params來接收。在這種情況下,應使用@RequestBody註解配合一個POJO或者Map來接收JSON資料。

  • 如果請求中包含陣列或列表型別的引數,如param=arrayValue1&param=arrayValue2,透過Map只能獲取到其中的一個值(通常是最後一個)。若需要處理這種型別的引數,可以使用@RequestParam List<String>@RequestParam String[]

  • @RequestParam是可選的,如果方法引數是Map<String, String>(或MultiValueMap<String, String>)型別,Spring MVC預設會將HTTP請求引數對映到該引數。

使用@RequestParam Map<String, String> params是處理HTTP請求引數的一種靈活方式,適用於需要訪問多個請求引數但又不想為每個引數單獨宣告方法引數的情況。

2 註解@RequestParam可以用來接收form表單提交的資料嗎?前面為什麼提到使用發出Post請求

是的,使用@RequestParam Map<String, String> params可以接收透過表單提交的資料。當提到使用POST請求的原因是,表單提交通常以POST方法進行,尤其是當表單資料包含大量資訊或包含敏感資訊(如密碼)時,因為POST方法不會將資料暴露在URL中,從而提供了更好的隱私保護。

表單資料通常以application/x-www-form-urlencoded的媒體型別提交,這意味著表單資料被編碼為鍵值對,就像URL的查詢字串一樣。這種資料格式可以透過@RequestParam直接接收,不論是對映到具體的方法引數還是聚合到Map<String, String>中。

表單提交示例

假設你有一個HTML表單:

<form action="/submitForm" method="post">
<input type="text" name="username" />
<input type="password" name="password" />
<button type="submit">Submit</button>
</form>

當使用者填寫此表單並點選提交時,瀏覽器會向/submitForm傳送一個POST請求,其中包含了輸入的使用者名稱和密碼。在Spring MVC的控制器中,可以這樣接收資料:

@PostMapping("/submitForm")
public String handleSubmit(@RequestParam Map<String, String> params) {
String username = params.get("username");
String password = params.get("password");
// 處理資料...
return "resultPage";
}

這裡,@RequestParam Map<String, String> params會收集表單中所有的輸入欄位(input)作為鍵值對。然後你可以透過鍵名訪問特定的值。

為什麼提到POST請求

  • 安全性:與GET請求相比,POST請求不會將資料直接暴露在URL中,適合提交敏感資訊。

  • 資料大小:理論上,POST請求的資料大小沒有限制,適合提交大量資料。

  • 適用性:表單提交是建立或更新資源的常見方式,POST方法語義上適用於這些操作。

儘管使用@RequestParam Map<String, String> params可以接收表單資料,但對於複雜的表單或當你需要將表單資料直接對映到一個Java物件時,推薦使用@ModelAttribute註解,這樣可以更方便地處理表單資料。

3 data:{mobile:,password:} 對應後端JavaBean

image-20240419222423231

image-20240419223323952

注意前端傳送的json物件的屬性名要和後端JavaBean物件的屬性名一致才會封裝成功

  $.ajax({
url: "/login/doLogin",
type: "POST",
data: {
mobile: $("#mobile").val(),
password: password
},
success: function (data) {
if (data.code == 200) {
alert(data.message)
} else {
alert(data.message)
}
},
error: function () {
alert("失敗");
}
});

package com.hspedu.seckill.vo;

import lombok.Data;

/**
* @author yangda
* @create 2024-04-19-16:12
* @description: 接收使用者登入時,傳送的資訊 (mobile,password)
*/
@Data
public class LoginVo {


private String mobile;
private String password;

}

    @RequestMapping("/doLogin")
@ResponseBody //加上該註解,就不會被解析為檢視了。即不會按照templates的檢視,而是返回json資料
public RespBean doLogin(LoginVo loginVo,
HttpServletRequest request,
HttpServletResponse response){

log.info("{}",loginVo);

return RespBean.success(); //預設請求轉發到templates/login.html
}

4 當後端使用@ResponseBody返回一個Long型別的資料給前端,前端接收到引數JavaScript能夠正確地將Long型別的資料轉換為數字,因此你可以放心地使用if (data.obj > 0) {這種比較方法。

其中data.obj就是Long型別的資料

理解和處理從後端傳遞的Long型別資料在前端的情況需要考慮多個方面,包括後端如何處理資料、前端如何接收資料以及資料在前端的處理方式。接下來,我將詳細整理這些方面,並給出相應的程式碼示例。

實際上,JavaScript處理從後端返回的Long型別資料時,是在解析JSON格式資料時進行的型別轉換。由於JSON中並沒有顯式的型別宣告,因此在JavaScript中解析後的資料型別可能會根據其值的大小和格式而自動轉換為數字型別。這種轉換是JavaScript引擎自動完成的,而不是嚴格意義上的“正確轉換”。

在前端接收到JSON格式資料後,JavaScript引擎會根據其值的特徵自動將其轉換為適當的型別。對於表示整數的值,如果其範圍在JavaScript能夠表示的整數範圍內,那麼它會被轉換為數字型別。因此,即使後端返回的資料是Long型別,在前端透過AJAX接收並解析後,其型別可能會被轉換為數字型別,從而可以使用數字的比較方法進行處理。

後端處理:

  1. Controller層:在Controller層,通常使用@ResponseBody註解將方法返回的物件直接轉換為JSON格式的響應資料傳送給前端。如果返回的資料是Long型別,則會自動轉換為對應的JSON格式。

    @RequestMapping("/seckillResult")
    @ResponseBody
    public RespBean getSeckillResult(User user, Long goodsId){
    Long seckillResult = orderService.getSeckillResult(user, goodsId);
    return RespBean.success(seckillResult);
    }

前端接收和處理:

  1. AJAX請求:前端透過AJAX請求從後端獲取資料,通常使用JSON格式接收響應資料。Long型別資料在JSON中會被轉換為相應的數字型別。

    $.ajax({
    url: '/seckillResult',
    type: 'POST',
    data: {
    user: userId,
    goodsId: goodsId
    },
    success: function(data) {
    // 處理從後端返回的Long型別資料
    if (data.obj > 0) {
    // 執行某些操作,表示數值大於0
    } else if (data.obj == 0) {
    // 執行某些操作,表示數值等於0
    } else if (data.obj == -1) {
    // 執行某些操作,表示數值等於-1
    } else {
    // 執行某些操作,表示其他情況
    }
    },
    error: function() {
    // 處理請求失敗情況
    }
    });
  2. 資料型別處理:前端接收到的Long型別資料可以直接用於數值比較,JavaScript會自動將其轉換為數字型別。可以使用比較運算子(>=====)來判斷數值的大小或相等關係。

示例說明:

假設後端返回的JSON資料格式如下:

{
"code": 200,
"obj": 12345 //這裡是Long型別,轉換為json後的結果
}

在前端接收到這個資料後,可以這樣處理:

success: function(data) {
// 處理從後端返回的Long型別資料
if (data.obj > 0) {
// 執行某些操作,表示數值大於0
} else if (data.obj == 0) {
// 執行某些操作,表示數值等於0
} else if (data.obj == -1) {
// 執行某些操作,表示數值等於-1
} else {
// 執行某些操作,表示其他情況
}
}

這樣,在前後端資料互動過程中,Long型別資料能夠被正確處理和比較,保證了資料的準確性和可靠性。

5 在HTTP請求中,資料可以透過不同的方式傳送,主要取決於請求的型別(如GET、POST)和內容型別(Content-Type)。這裡讓我們詳細瞭解URL請求引數和表單傳送時的情況:

1. URL請求引數 (常用於GET請求)

  • 格式:當資料透過URL請求引數傳送時,它們附加在URL的末尾,通常以問號(?)開始,後面跟隨一系列的鍵值對。鍵值對之間由&符號分隔。

  • 例子http://example.com/api?user=userId&goodsId=goodsId

  • 用途:這種方式通常用於GET請求,用於查詢字串傳遞輕量級資料。

  • 資料接收:後端框架(如Spring MVC)透過註解(如@RequestParam)可以輕鬆捕獲這些URL引數並將它們對映到控制器方法的引數上。

2. Form表單傳送 (常用於POST請求)

  • Content-Typeapplication/x-www-form-urlencoded

  • 格式:當使用表單提交資料時,表單資料被編碼為鍵值對,就像URL查詢字串一樣。每對鍵值用=連線,而鍵值對之間用&分隔。

  • 例子:在HTML表單中,輸入欄位(如 <input type="text" name="user" value="userId">)會被編碼為 user=userId&goodsId=goodsId

  • 用途:這種方式廣泛用於在網頁表單提交時傳送資料到伺服器。

  • 資料接收:後端(如使用Spring MVC)會自動解析這些編碼後的表單資料,並將它們對映到控制器方法的相應引數上。

特別注意

如果要傳送JSON資料或其他格式的複雜資料,需要使用不同的 Content-Type,如application/json,並通常與POST或PUT請求一起使用。在這種情況下,資料以JSON格式在請求體中傳送,後端需要用例如@RequestBody註解來解析JSON資料。

總之,URL請求引數和表單資料傳送都是編碼為鍵值對的形式,不同之處在於它們在HTTP請求中的位置和一些細節處理方式。對於表單提交,資料通常在POST請求的請求體中傳送,而URL請求引數則附在URL末尾。

6 在使用jQuery的$.ajax方法時,引數可以透過dataparams屬性來傳遞。這兩種方式的資料格式和後端接收方式有所不同。下面我們將分別解析這兩種情況,並附上程式碼示例。

1. 使用 data 屬性攜帶引數

當使用data屬性傳遞引數時,這些引數會被包含在HTTP請求的體(body)中,適用於POST請求。如果沒有指定Content-Type,預設情況下,data屬性中的資料將以application/x-www-form-urlencoded格式傳送。

前端程式碼示例(使用 data):

$.ajax({
url: '/api/resource',
type: 'POST',
data: {
userId: "123",
goodsId: "456"
},
success: function(response) {
console.log("Response:", response);
}
});

後端程式碼示例(Spring MVC接收POST資料):

@PostMapping("/api/resource")
public ResponseEntity<?> receivePostData(@RequestParam("userId") String userId, @RequestParam("goodsId") String goodsId) {
// 處理資料
return ResponseEntity.ok("Received userId: " + userId + " and goodsId: " + goodsId);
}

2. 使用 params 屬性攜帶引數

params屬性通常用於在URL中傳遞引數,這種方式適合於GET請求。引數以查詢字串的形式附加到URL後面。

前端程式碼示例(使用 params):

$.ajax({
url: '/api/resource',
type: 'GET',
params: {
userId: "123",
goodsId: "456"
},
success: function(response) {
console.log("Response:", response);
}
});

注意:在jQuery中,通常不使用params關鍵字,而是使用data關鍵字即可,無論是POST還是GET請求,data屬性都可以自動將資料加到URL中或放到請求體中,具體取決於請求型別。上述params用法在axios中更常見。對於jQuery的GET請求,使用data屬性的程式碼如下:

$.ajax({
url: '/api/resource',
type: 'GET',
data: {
userId: "123",
goodsId: "456"
},
success: function(response) {
console.log("Response:", response);
}
});

後端程式碼示例(Spring MVC接收GET資料):

@GetMapping("/api/resource")
public ResponseEntity<?> receiveGetData(@RequestParam("userId") String userId, @RequestParam("goodsId") String goodsId) {
// 處理資料
return ResponseEntity.ok("Received userId: " + userId + " and goodsId: " + goodsId);
}

總結

  • 當使用data時,資料預設在POST請求中放在請求體內,格式為application/x-www-form-urlencoded,除非指定其他Content-Typeapplication/json

  • 使用data屬性在GET請求中時,jQuery會自動將資料轉化為URL查詢引數形式。

  • 在Spring MVC中,無論是POST還是GET請求,都可以使用@RequestParam註解來接收URL引數或請求體中的表單資料。

7 當前端傳送的資料為JSON字串時,後端接收和封裝引數的方式通常依賴於使用的框架。

以Spring MVC為例,你可以使用@RequestBody註解來接收JSON字串並自動將其對映到Java物件中。這需要前端在傳送請求時設定正確的Content-Typeapplication/json,並且後端需要有相應的類來對映JSON資料結構。

前端傳送JSON資料的示例

$.ajax({
url: '/api/resource',
type: 'POST',
contentType: 'application/json', // 設定傳送內容型別為 JSON
data: JSON.stringify({
userId: "123",
goodsId: "456"
}),
success: function(response) {
console.log("Response:", response);
},
error: function(xhr, status, error) {
console.error("Error:", error);
}
});

後端接收JSON資料的示例

假設你有一個Java類UserRequest,該類有userIdgoodsId屬性,可以用來對映前端傳送的JSON資料:

public class UserRequest {
private String userId;
private String goodsId;

// getters and setters
public String getUserId() {
return userId;
}
public void setUserId(String userId) {
this.userId = userId;
}
public String getGoodsId() {
return goodsId;
}
public void setGoodsId(String goodsId) {
this.goodsId = goodsId;
}
}

接下來,你可以在Spring MVC的控制器中使用@RequestBody註解來接收這個JSON資料:

@PostMapping("/api/resource")
public ResponseEntity<?> handleRequest(@RequestBody UserRequest userRequest) {
// 使用userRequest中的資料進行處理
System.out.println("Received userId: " + userRequest.getUserId() + " and goodsId: " + userRequest.getGoodsId());
return ResponseEntity.ok("Received JSON data");
}

關鍵點

  • 設定ContentType:確保前端在傳送AJAX請求時設定contentType: 'application/json',這樣資料才會以JSON格式傳送,並且後端才能正確解析。

  • 使用@RequestBody:在Spring MVC控制器中使用@RequestBody註解可以自動解析請求體中的JSON資料並將其對映到對應的Java物件。

  • 資料轉換:後端框架通常利用如Jackson或Gson這樣的庫來自動從JSON轉換到Java物件。

透過這種方式,後端可以方便地處理複雜的JSON結構,並且可以利用型別安全的優勢來運算元據。

8 ajax 在data中攜帶資料會根據請求型別不同get/post,攜帶資料的形式也不同

當發出的是GET 請求時,在data中的資料,會被放到url後面

GET /seckill/path?goodsId=1&captcha=14803

 $.ajax({
url: "/seckill/path",

type: "GET",

// captcha: captcha 中的第一個 captcha 需要和後端方法形參位置要封裝的引數名對應才可以封裝成功
data: {
goodsId: goodsId,
captcha: captcha,
},

image-20240504184430493

image-20240504184626700

後端可以使用的接收資料的形式為:

//方法: 獲取秒殺路徑
// captcha: captcha 中的第一個 captcha 需要和後端方法形參位置要封裝的引數名String captcha對應才可以封裝成功
@RequestMapping("/path")
@ResponseBody
public RespBean getPath(User user, Long goodsId,String captcha) {

在Spring MVC中,如果引數是基礎資料型別(如LongString)並且透過URL查詢引數傳遞,Spring MVC預設會嘗試將這些查詢引數對映到方法的引數上,不需要使用@RequestParam註解。

當發出的是POST 請求時,在data中的資料,會被放到請求體中

在POST請求中,如果不指定contentType,預設情況下data將以application/x-www-form-urlencoded格式傳送,即表單提交方式。

POST /seckill/path

 $.ajax({
url: "/seckill/path",

type: "POST",

// captcha: captcha 中的第一個 captcha 需要和後端方法形參位置要封裝的引數名對應才可以封裝成功
data: {
goodsId: goodsId,
captcha: captcha,
},

請求體中的資料形式為:

image-20240504185003151

goodsId=1&captcha=222

image-20240504184903874

後端可以使用的接收資料的形式為:

//方法: 獲取秒殺路徑
// captcha: captcha 中的第一個 captcha 需要和後端方法形參位置要封裝的引數名String captcha對應才可以封裝成功
@RequestMapping("/path")
@ResponseBody
public RespBean getPath(User user, Long goodsId,String captcha) {

在POST請求中,即使是application/x-www-form-urlencoded,Spring MVC同樣能夠將請求體中的表單資料對映到控制器方法的引數上,同樣不需要顯式使用@RequestParam

9 當使用Ajax進行資料傳輸時,資料的傳輸方式確實會受到HTTP請求型別(GET或POST)的影響。下面是詳細的解釋和分析,關於後端如何接收這些資料,以及在Spring MVC中使用註解的最佳實踐。

GET 請求

在GET請求中,資料透過URL傳遞。當你在jQuery的$.ajax設定中使用data物件時,jQuery會自動將這些資料轉換為URL查詢引數,附加到請求的URL後面。

前端示例:

$.ajax({
url: "/seckill/path",
type: "GET",
data: {
goodsId: goodsId,
captcha: captcha
}
});

後端接收(Spring MVC):

@RequestMapping("/path")
@ResponseBody
public RespBean getPath(User user, Long goodsId, String captcha) {
// 使用goodsId和captcha
}

在Spring MVC中,如果引數是基礎資料型別(如LongString)並且透過URL查詢引數傳遞,Spring MVC預設會嘗試將這些查詢引數對映到方法的引數上,不需要使用@RequestParam註解。

POST 請求

在POST請求中,如果不指定contentType,預設情況下data將以application/x-www-form-urlencoded格式傳送,即表單提交方式。

前端示例:

$.ajax({
url: "/seckill/path",
type: "POST",
data: {
goodsId: goodsId,
captcha: captcha
}
});

後端接收(Spring MVC):

@RequestMapping("/path")
@ResponseBody
public RespBean getPath(User user, Long goodsId, String captcha) {
// 使用goodsId和captcha
}

在POST請求中,即使是application/x-www-form-urlencoded,Spring MVC同樣能夠將請求體中的表單資料對映到控制器方法的引數上,同樣不需要顯式使用@RequestParam

使用@RequestParam

@RequestParam註解用於將請求引數對映到方法引數上。當你明確地想要表明這些引數是從請求的引數中得到的,可以使用此註解。@RequestParam適用於GET請求的查詢引數和POST請求的表單資料(application/x-www-form-urlencoded),但不適用於如application/json格式的請求體。

@RequestMapping("/path")
@ResponseBody
public RespBean getPath(
@RequestParam("goodsId") Long goodsId,
@RequestParam("captcha") String captcha) {
// 使用goodsId和captcha
}

總結

  1. 對於GET和POST請求(預設contentTypeapplication/x-www-form-urlencoded),Spring MVC可以自動處理URL引數和表單資料,無需特別註解。

  2. 使用@RequestParam 增加程式碼的可讀性和明確性,對於基礎資料型別尤其有效,無論是GET還是POST請求。

  3. 對於JSON格式的POST請求,需要使用@RequestBody註解,並且前端需要設定contentType: 'application/json'

Spring MVC在沒有註解的情況下能夠靈活處理多種常見的資料傳遞方式,使得開發更為便捷。

10 對於 @RequestParam 的使用,確實主要是用來獲取URL請求引數的。它是用於處理來自URL查詢字串或表單資料(在使用 application/x-www-form-urlencoded 編碼時)的情況。在HTTP GET請求中,這些引數來自URL的查詢部分;在HTTP POST請求中,這些引數來自提交的表單資料。

@RequestParam 的用途

  • 獲取URL引數:無論是GET還是POST請求,只要引數是附在URL後(例如?key=value),@RequestParam 都可以用來獲取這些引數。

  • 讀取表單資料:在POST請求中,如果表單的Content-Typeapplication/x-www-form-urlencoded@RequestParam 也可以用來讀取表單內的資料。

@RequestParam 不能用於

  • 非表單編碼的POST資料:如果POST請求中的資料是以application/json或其他非表單編碼格式傳送的,@RequestParam 就無法獲取這些資料。在這種情況下,你應該使用 @RequestBody 來獲取請求體中的JSON或其他格式的資料。

這意味著,如果你有一個以JSON格式傳送資料的POST請求,像這樣:

$.ajax({
url: "/api/data",
type: "POST",
contentType: "application/json",
data: JSON.stringify({ key: "value" }),
success: function(response) {
console.log(response);
}
});

後端應使用 @RequestBody 來接收資料:

@PostMapping("/api/data")
public ResponseEntity<String> postData(@RequestBody Map<String, Object> data) {
// 處理資料
return ResponseEntity.ok("Received data with key: " + data.get("key"));
}

在這個例子中,@RequestBody 註解告訴Spring框架從請求體中讀取資料,並將其自動轉換成相應的Java物件。

總結一下,@RequestParam 非常適合處理URL引數和表單提交資料,而對於JSON等其他請求體內容,則需要使用 @RequestBody。這兩種註解的使用取決於請求的具體內容和格式。

相關文章