【原創】淺談ajax和axios的使用不同點和,以及Java接收引數的形式
引言
有很多人的誤區就是使用axios或者ajax傳遞json引數時,後端必須要用某種手段處理,例如 很多人認為axios傳遞json必須用mvc的@RequestBody處理,因為axios預設的ContentType為application/json ,這種‘必須’的表述是錯誤的,是對程式設計的誤解,程式不是一成不變的。
我們在入門時常用form表單進行資料提交操作,此時的請求頭中使用的content-type 是application/x-www-form-urlencoded 也就是formData 表單格式資料,表單格式的資料傳遞特點就是key value形式的鍵值對,form表單會進行處理成 "name=xxx&age=xxx" 的形式。如下
<form action="http://localhost:8080/user/login1.do" method="post"> 使用者名稱<input type="text" v-model="formData.username" name="username"><br> 密碼<input type="password" v-model="formData.password" name="password" ><br> <input type="submit" value="提交"> </form>
後端使用springmvc取值,這也是最常規的取值方案了
@RequestMapping("/login1") @ResponseBody public Result login1(String username,String password){ System.out.println("login1>>>>>>>u:"+username+",p:"+password); return new Result(true,"登入成功"); }
Ajax
我們在引言中清楚的知道了form表單的傳參特性,下面來講一下ajax,此時我們來試一下
var vue = new Vue({ ..... data: { // 提交給後臺的資料 都是在data中宣告的 formData: { username: '', password: '' }, .....
let baseUrl = "http://localhost:8080/user/login1.do"; // 傳送 post 請求 $.ajax({ url: baseUrl, async: true, data: this.formData, success: function (res) { console.log(res) }, type: "post", dataType: "json" })
後端接收
@RequestMapping("/login2") @ResponseBody public Result login2(LoginParam param) { System.out.println("login2>>>>>>>u:" + param.getUsername() + ",p:" + param.getPassword()); return new Result(true, "登入成功"); }
從案例中我們發現 ajax 的預設的contentType 也是application/x-www-form-urlencoded,並且和form標籤做了相同的事情,那就是對一個json格式的資料進行了格式轉換,也變成了form標籤中的處理格式 "name=xxx&age=xxx" ,這裡也是很多人的誤區,很多人認為json只能用@RequestBody 搭配application/json使用,卻沒有注意到ajax預設的ConentType也是formData,後端也是常規的接收方式不多贅述。 springmvc傳參https://www.cnblogs.com/xiaozhang666/p/13657846.html
擴充套件 ajax對應@RequestBody的接收
在使用是必須將contentType改為application/json 並且 json轉為json字串,如下
$.ajax({ url: baseUrl, async: true, data: JSON.stringify(this.formData), contentType: "application/json", success: function (res) { console.log(res) }, type: "post", dataType: "json" })
後端接受
@RequestMapping("/login3") @ResponseBody public Result login3(@RequestBody LoginParam param) { System.out.println("login3>>>>>>>u:" + param.getUsername() + ",p:" + param.getPassword()); return new Result(true, "登入成功"); }
Axios
使用過的人知道 axios的contentType預設為application/json
對於get方式的query傳值並沒有多大影響,只是data欄位換為params
let baseUrl = "http://localhost:8080/user/login1.do"; // 傳送 get 請求 axios({ method: 'get', url: baseUrl, params: this.formData }).then((res) => { console.log(res); })
我們發現此時的 contentType在 axios 中的get請求並沒有明確的指定,其實ajax的get時也沒有明確指出。
如圖 params 給我們做的事就是把一個json格式的資料轉換為 鍵值對並且把它拼接到url地址上,等效於
"http://localhost:8080/user/login1.do?username=" + this.formData.username + "&password=" + this.formData.password
重點
一、axios 的application/json傳遞引數
上面說過axios的contentType預設為application/json 那麼我們試驗一下post傳遞json格式
let baseUrl = "http://localhost:8080/user/login3.do"; // 傳送 post 請求 axios({ method: 'post', url: baseUrl, data: this.formData }).then((res) => { console.log(res); })
後端接收
@RequestMapping("/login3") @ResponseBody public Result login3(@RequestBody LoginParam param) { System.out.println("login3>>>>>>>u:" + param.getUsername() + ",p:" + param.getPassword()); return new Result(true, "登入成功"); }
我們此時發現這種axios寫法完全等效於ajax的以下寫法。。
$.ajax({ url: baseUrl, async: true, data: JSON.stringify(this.formData), contentType: "application/json", success: function (res) { console.log(res) }, type: "post", dataType: "json" })
就連後端接收引數都相同,那此時很明顯 axios替我們做了ajax中的JSON.stringify(this.formData) 的功能,就是將json 轉換成為json字串。
二、axios 的application/x-www-form-urlencoded傳遞引數 也就是 表單formData
上面的ajax預設為表單傳遞引數,直接傳json時ajax把json轉為鍵值對模仿了表單傳遞。那麼我們有一個大膽的假設,將axios的contentType設定為application/x-www-form-urlencoded ,這樣我們是不是也可以用標準的json格式和常規的springmvc獲取引數的形式獲取到引數呢,而不再使用 application/json 搭配 @RequestBody了。
直接開搞,將請求頭Content-Type 重新設定
let baseUrl = "http://localhost:8080/user/login1.do"; // 傳送 post 請求 axios({ headers: {'Content-Type': 'application/x-www-form-urlencoded'}, method: 'post', url: baseUrl, data: this.formData }).then((res) => { console.log(res); })
java常規接收
@RequestMapping("/login2") @ResponseBody public Result login2(LoginParam param) { System.out.println("login2>>>>>>>u:" + param.getUsername() + ",p:" + param.getPassword()); return new Result(true, "登入成功"); }
第一次結果
我們發現ContentType的值修改了,但是formData的格式卻成了一個json字串格式,並不是from表單標準的鍵值對"name=xxx&age=xxx" 格式,所以常規的引數繫結無法接收到引數,這裡查了一下資料,這裡需要手動的轉換一下,將json轉換為鍵值對,用axios文件提供的第三方 Qs.stringify() 方法轉換。
https://github.com/ljharb/qs 下的dist 的 qs.js 進行引入到你的專案中。
let baseUrl = "http://localhost:8080/user/login1.do"; // 傳送 post 請求 axios({ headers: {'Content-Type': 'application/x-www-form-urlencoded'}, method: 'post', url: baseUrl, data: Qs.stringify(this.formData) }).then((res) => { console.log(res); })
這樣我們再試一下
此時發現不同了,那就是原本的json串被轉換成了鍵值對的形式,那麼現在已經符合了form表單的傳送資料的格式,我們再看看後端
已經取到了。
最後總結幾點
- axios替我們做了json 轉 json串的工作,JSON.stringify(this.formData)。
- ajax替我們做了 json轉鍵值對的工作 ,Qs.stringify(this.formData)。
- 兩種非同步請求方法都沒有硬性的要求,只不過是ContentType的轉變。
- application/x-www-form-urlencoded 屬性要傳鍵值對,application/json 屬性傳值為 json字串