使用axios和spring?boot?交互及使用步驟
Axios
Axios是一個基于Promise的HTTP庫,可以發(fā)送get、post等請求,它作用于瀏覽器和Node.js中。當運行在瀏覽器時,使用XMLHttpRequest接口發(fā)送請求;當運行在Node.js時,使用HTTP對象發(fā)送請求。

使用步驟:
第一步:安裝axios 略
第二步:在項目中使用Axios時,通常的做法是先將Axios封裝成一個模塊,然后在組件中導入模塊。
第三步:編寫各種請求 這里只說明 基本的get請求和post請求。
request({
url: '請求路徑',
method: 'get',
params: { 參數(shù) }
}).then(res => {
console.log(res)
}).catch(error => {
console.log(error)
})get請求:
/**
* 發(fā)送GET請求
*/
export const getReq = (url, params) => {
return axios({
method: 'get',
params, // 使用params而非data
url: `${base}${url}`,
headers: {
'token': localStorage.getItem("token"),
}
});
}使用它:
// 獲取用戶列表,帶分頁參數(shù)
getReq('/api/users', { page: 1, pageSize: 10 })
.then(res => {
console.log('用戶列表:', res.data);
})
.catch(err => {
console.error('請求失敗:', err);
});post請求:
request({
url: '請求路徑',
method: 'post',
data: { 參數(shù) }
}).then(res => {
console.log(res)
}).catch(error => {
console.log(error)
})export const postReq = (url, params) => {
return axios({
method: 'post',
url: `${base}${url}`,
data: params,
headers: {
'token': localStorage.getItem("token"),
}
});
異步請求調(diào)用中 async+await 的應用
代碼:
export const fetchData = async (url, params) => {
try {
const response = await axios({
method: 'get',
params, // 修正:使用 params 而非 data
url: `${base}${url}`,
headers: {
'token': localStorage.getItem('token'),
}
});
return response.data;
} catch (error) {
console.error('請求失敗:', error);
throw error; // 修正:重新拋出錯誤,讓調(diào)用者處理
}
};async+await 的概念
async/await 是一種建立在Promise之上的編寫異步或非阻塞代碼的新方法。async 是異步的意思,而 await 是 async wait的簡寫,即異步等待。
所以從語義上就很好理解 async 用于聲明一個 函數(shù) 是異步的,而await 用于等待一個異步方法執(zhí)行完成。
那么想要同步使用數(shù)據(jù)的話,就可以使用 async+await 。
說明:async函數(shù)返回的是一個 Promise 對象。async 函數(shù)(包含函數(shù)語句、函數(shù)表達式、Lambda表達式)會返回一個 Promise 對象,如果在函數(shù)中 一個直接量,async 會把這個直接量通過promise.solve() 封裝成 Promise 對象。
如果 async 函數(shù)沒有返回值, 它會返回 promise.solve(underfined)。
await 等待的是一個表達式,這個表達式的計算結(jié)果是 Promise 對象或者其它值(換句話說,await 可以等任意表達式的結(jié)果)。
如果它等到的不是一個 Promise 對象,那 await 表達式的運算結(jié)果就是它等到的東西。
如果它等到的是一個 Promise 對象,await 就忙起來了,它會阻塞后面的代碼,等著 Promise 對象 resolve,然后得到 resolve 的值,作為 await 表達式的運算結(jié)果。
調(diào)用方式:
Promise 鏈式調(diào)用:.then().catch() 同步風格的
await:在 async 函數(shù)內(nèi)部使用
- romise 鏈式調(diào)用適合 “非阻塞、并行、兼容舊環(huán)境” 的場景,強調(diào)異步操作的獨立性。
- async/await適合 “順序依賴、復雜流程、高可讀性” 的場景,讓異步代碼更接近同步思維模式。
1. 使用 .then() 和 .catch() 鏈式調(diào)用
import { fetchData } from './api'; // 假設從 api.js 導入
// 調(diào)用 fetchData 獲取用戶列表
fetchData('/api/users', { page: 1, pageSize: 10 })
.then(data => {
console.log('用戶列表:', data);
// 處理返回的數(shù)據(jù)(如更新組件狀態(tài))
})
.catch(error => {
console.error('請求失敗:', error);
// 顯示錯誤消息(如彈框提示)
});
//其他邏輯會和fetchData同步進行
..... 2. 在 async 函數(shù)內(nèi)部使用 await
async function loadUsers() {
try {
// 等待請求完成并獲取數(shù)據(jù)
const data = await fetchData('/api/users', { page: 1, pageSize: 10 });
console.log('用戶列表:', data);
// 可以直接使用同步風格的代碼處理數(shù)據(jù)
const firstUser = data.list[0];
console.log('第一個用戶:', firstUser);
} catch (error) {
console.error('請求失敗:', error);
// 錯誤處理邏輯
}
}
// 調(diào)用 async 函數(shù)
loadUsers();當執(zhí)行 loadUsers() 函數(shù)時,它會返回一個 Promise 對象,并且其內(nèi)部邏輯會以異步方式執(zhí)行。以下是詳細解釋:
1. 函數(shù)返回值:Promise 對象
原因:任何使用
async關(guān)鍵字聲明的函數(shù)都會自動返回一個 Promise。
示例驗證:
javascript
const result = loadUsers(); console.log(result instanceof Promise); // 輸出: true
Promise 的狀態(tài):
- 成功(fulfilled):當
fetchData請求成功且沒有拋出異常時,Promise 會 resolve,并傳遞loadUsers函數(shù)的返回值(若沒有顯式返回,默認返回undefined)。 - 失?。╮ejected):當
fetchData拋出異常,或loadUsers內(nèi)部try塊中的代碼報錯時,Promise 會 reject,并傳遞錯誤對象。
- 成功(fulfilled):當
2. 函數(shù)執(zhí)行流程(異步本質(zhì))
console.log('開始執(zhí)行');
loadUsers();
console.log('結(jié)束執(zhí)行');
// 輸出順序:
// 開始執(zhí)行
// 結(jié)束執(zhí)行
// (等待 fetchData 請求完成后)
// 用戶列表: ...
// 第一個用戶: ...- 關(guān)鍵特點:
loadUsers()函數(shù)被調(diào)用后立即返回 Promise,不會阻塞后續(xù)代碼執(zhí)行。await fetchData(...)僅暫停函數(shù)內(nèi)部的執(zhí)行,不會影響外部代碼(如console.log('結(jié)束執(zhí)行')會先于fetchData的結(jié)果輸出)。當
fetchData的 Promise 解決(成功 / 失敗)時,loadUsers內(nèi)部的await會恢復執(zhí)行,并決定 Promise 的最終狀態(tài)。
3. Promise 的解決(resolve)情況
當 fetchData 請求成功且 try 塊內(nèi)代碼無異常時:
loadUsers的 Promise 會 resolve,返回值為undefined(因為函數(shù)沒有顯式return)。
等價于:
javascript
async function loadUsers() {
// ... 代碼 ...
return undefined; // 隱式返回
}可通過 .then() 捕獲結(jié)果:
loadUsers().then(result => {
console.log('loadUsers 返回值:', result); // 輸出: undefined
});4. Promise 的拒絕(reject)情況
當出現(xiàn)以下情況時,loadUsers 的 Promise 會 reject:
fetchData 拋出錯誤:
javascript
fetchData('/api/users', { page: 1 })
.catch(error => {
throw new Error('請求失敗: ' + error); // 被 loadUsers 的 catch 捕獲
});try 塊內(nèi)其他代碼報錯:
const firstUser = data.list[0]; // 若 data.list 為 undefined,會拋出 TypeError
catch 塊中重新拋出錯誤:
catch (error) {
console.error('請求失敗:', error);
throw error; // 重新拋出,導致 Promise reject
}可通過 .catch() 捕獲錯誤:
loadUsers().catch(error => {
console.error('loadUsers 錯誤:', error);
});5. 與 Promise 鏈式調(diào)用的等價關(guān)系
loadUsers 函數(shù)的異步邏輯等價于以下 Promise 寫法:
function loadUsers() {
return fetchData('/api/users', { page: 1, pageSize: 10 })
.then(data => {
console.log('用戶列表:', data);
const firstUser = data.list[0];
console.log('第一個用戶:', firstUser);
// 隱式返回 undefined
})
.catch(error => {
console.error('請求失敗:', error);
throw error; // 重新拋出錯誤,保持 Promise 鏈的異常傳遞
});
}6. 如何獲取函數(shù)的執(zhí)行結(jié)果?
(1)使用 .then()
loadUsers()
.then(() => {
console.log('數(shù)據(jù)處理完成');
})
.catch(error => {
console.error('處理失敗:', error);
});(2)在另一個 async 函數(shù)中使用 await
async function processData() {
try {
await loadUsers(); // 等待 loadUsers 的 Promise 解決
console.log('loadUsers 執(zhí)行完畢');
} catch (error) {
console.error('processData 捕獲到錯誤:', error);
}
}- 返回值:
loadUsers()始終返回一個 Promise 對象。 - 狀態(tài)由內(nèi)部邏輯決定:
- 成功時(
fetchData正常返回且無代碼錯誤):Promise resolve,返回undefined。 - 失敗時(
fetchData報錯或代碼異常):Promise reject,傳遞錯誤對象。
- 成功時(
- 異步本質(zhì):函數(shù)內(nèi)部使用
await暫僅停自身執(zhí)行,不阻塞主線程,整體仍為異步操作。
應用transformRequest
export const postRequest = (url, params) => {
return axios({
method: 'post',
url: `${base}${url}`,
data: params,
transformRequest: [function (data) {
let ret = '';
for (let key in data) {
ret += encodeURIComponent(key) + '=' + encodeURIComponent(data[key]) + '&';
}
return ret;
}],
headers: {
'Content-Type': 'application/x-www-form-urlencoded', // 修正為表單格式
}
});
}說明:
數(shù)據(jù)格式與請求頭的關(guān)系:
application/json:請求體應為 JSON 格式(如{"key": "value"})。application/x-www-form-urlencoded:請求體應為表單格式(如key=value&key2=value2)。
transformRequest的影響:- 當前代碼將對象轉(zhuǎn)換為表單格式數(shù)據(jù),但請求頭卻聲明為 JSON,導致后端可能無法解析。
- 若后端期望 JSON 數(shù)據(jù),應移除
transformRequest并保持application/json頭。
正確的搭配方式:
數(shù)據(jù)格式 Content-Type 是否需要 transformRequest JSON application/json 不需要 表單數(shù)據(jù) application/x-www-form-urlencoded 需要(如當前函數(shù)) 二進制文件 / 表單 multipart/form-data 不需要
函數(shù)調(diào)用示例
場景 1:提交表單數(shù)據(jù)到后端
import { postRequest } from './api.js'; // 導入函數(shù)
// 表單數(shù)據(jù)
const formData = {
username: 'test_user',
password: '123456',
email: 'test@example.com'
};
// 調(diào)用函數(shù)
postRequest('/api/register', formData)
.then(response => {
console.log('注冊成功:', response.data);
})
.catch(error => {
console.error('注冊失敗:', error);
});場景 2:發(fā)送 JSON 數(shù)據(jù)(需修改函數(shù))
如果需要發(fā)送 JSON 數(shù)據(jù),應使用以下封裝:
export const postJsonRequest = (url, params) => {
return axios({
method: 'post',
url: `${base}${url}`,
data: params,
headers: {
'Content-Type': 'application/json',
}
});
}
// 調(diào)用示例
const userData = {
name: '張三',
age: 25,
hobbies: ['閱讀', '編程']
};
postJsonRequest('/api/users', userData)
.then(res => console.log(res.data));調(diào)用注意事項
參數(shù)說明:
url:API 路徑(如/api/login),會自動拼接base(如http://localhost:8080)。params:需要發(fā)送的數(shù)據(jù)對象,會被transformRequest轉(zhuǎn)換為表單格式。
錯誤處理:
在調(diào)用時添加.catch()處理請求失?。?/p>
postRequest(...).catch(error => {
const status = error.response?.status || '網(wǎng)絡錯誤';
const message = error.response?.data?.message || '請求失敗';
console.error(`狀態(tài)碼 ${status}: ${message}`);
});與其他請求函數(shù)的區(qū)別:
- 若后端接口需要不同的 Content-Type,應創(chuàng)建不同的封裝函數(shù)(如 JSON 格式、文件上傳等)。
- 數(shù)據(jù)為對象格式(如
{key: value}) - 后端接口期望表單數(shù)據(jù)(
application/x-www-form-urlencoded) - 添加錯誤處理邏輯以應對請求失敗的情況
如果需要發(fā)送 JSON 數(shù)據(jù),最好創(chuàng)建專門的函數(shù),不需要transformRequest。
對不同格式的數(shù)據(jù),spring boot 端的處理:
| 場景 | 推薦注解 | 示例 |
|---|---|---|
| 處理 JSON 數(shù)據(jù) | @RequestBody | @RequestBody User user |
| 處理簡單表單數(shù)據(jù)(少量參數(shù)) | @RequestParam | @RequestParam("username") String name |
| 處理復雜表單數(shù)據(jù)(對象綁定) | @ModelAttribute | @ModelAttribute User user |
| 同時支持 JSON 和表單(需自定義) | @RequestBody + 轉(zhuǎn)換器 | 配置 FormHttpMessageConverter |
建議:
- JSON:統(tǒng)一使用
@RequestBody,前端發(fā)送application/json。 - 表單:使用
@RequestParam或@ModelAttribute,前端發(fā)送application/x-www-form-urlencoded。 - 避免混用:不要試圖用
@RequestBody同時處理兩種格式,會增加復雜度。
postJsonRequest
export const postJsonRequest = (url, params) => {
return axios({
method: 'post',
url: `${base}${url}`,
data: params, // axios 自動將對象序列化為 JSON
headers: {
'Content-Type': 'application/json',
}
});
}調(diào)用方式例子:
// 發(fā)送用戶數(shù)據(jù)
const userData = {
username: 'john',
email: 'john@example.com',
isActive: true
};
postJsonRequest('/api/users', userData)
.then(res => console.log('用戶創(chuàng)建成功:', res.data))
.catch(err => console.error('錯誤:', err));發(fā)送表單數(shù)據(jù)(application/x-www-form-urlencoded)
export const postFormRequest = (url, params) => {
return axios({
method: 'post',
url: `${base}${url}`,
data: params,
transformRequest: [function (data) {
let ret = '';
for (let key in data) {
ret += encodeURIComponent(key) + '=' + encodeURIComponent(data[key]) + '&';
}
return ret;
}],
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
}
});
}調(diào)用方式例子:
// 提交登錄表單
const loginData = {
username: 'admin',
password: '123456',
rememberMe: true
};
postFormRequest('/api/login', loginData)
.then(res => {
localStorage.setItem('token', res.data.token);
console.log('登錄成功');
})
.catch(err => alert('登錄失敗: ' + err.message));比與適用場景及編碼問題
| 方案 | Content-Type | 數(shù)據(jù)格式 | 后端適配 | 前端寫法 |
|---|---|---|---|---|
| 方案一(JSON) | application/json | {"key":"value"} | Spring Boot 的 @RequestBody | 直接傳遞對象 |
| 方案二(表單) | application/x-www-form-urlencoded | key=value&key2=value2 | Spring Boot 的 @RequestParam/@ModelAttribute | 需手動或用庫序列化 |
后端接口匹配:
- JSON 格式:確保后端使用
@RequestBody注解 - 表單格式:確保后端使用
@RequestParam或@ModelAttribute
- JSON 格式:確保后端使用
編碼問題:
- 表單數(shù)據(jù)中的特殊字符(如中文)會被
encodeURIComponent自動編碼 - JSON 數(shù)據(jù)中的中文會被序列化為 Unicode 字符(如
\u4e2d)
- 表單數(shù)據(jù)中的特殊字符(如中文)會被
putRequest :
export const putRequest = (url, params) => {
return axios({
method: 'put',
url: `${base}${url}`,
data: params,
transformRequest: [function (data) {
if (!data) return '';
const ret = [];
for (let key in data) {
if (data.hasOwnProperty(key)) {
const value = data[key];
// 處理值為 null 或 undefined 的情況
const encodedValue = value === null || value === undefined ? '' : encodeURIComponent(value);
ret.push(`${encodeURIComponent(key)}=${encodedValue}`);
}
}
// 使用 join 避免末尾多余的 &
return ret.join('&');
}],
headers: {
'Content-Type': 'application/x-www-form-urlencoded'
}
})
.catch(error => {
console.error('PUT 請求失敗:', error);
// 可以在這里進行統(tǒng)一的錯誤處理
throw error; // 繼續(xù)拋出錯誤,讓調(diào)用者可以捕獲
});
};參考資料
vue+element UI 學習總結(jié)筆記(一)_vue+elementui
到此這篇關(guān)于使用axios和spring boot 交互及使用步驟的文章就介紹到這了,更多相關(guān)axios和spring boot 交互內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Mybatis返回map集合時,列的順序與select不一致問題
這篇文章主要介紹了Mybatis返回map集合時,列的順序與select不一致問題,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2022-01-01
JsonFormat與@DateTimeFormat注解實例解析
這篇文章主要介紹了JsonFormat與@DateTimeFormat注解實例解析,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友可以參考下2019-12-12
使用React和springboot做前后端分離項目的步驟方式
這篇文章主要介紹了使用React和springboot做前后端分離項目的步驟方式,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教2023-08-08
Java中如何使用?byte?數(shù)組作為?Map?的?key
本文將討論在使用HashMap時,當byte數(shù)組作為key時所遇到的問題及其解決方案,介紹使用String和List這兩種數(shù)據(jù)結(jié)構(gòu)作為臨時解決方案的方法,感興趣的朋友跟隨小編一起看看吧2023-06-06
Java for循環(huán)和foreach循環(huán)的性能對比分析
這篇文章主要介紹了Java for循環(huán)和foreach循環(huán)的性能對比分析,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2021-09-09
SpringBoot中Filter?bean如何添加到Servlet容器
這篇文章主要介紹了SpringBoot中Filter bean是怎么被添加到Servlet容器中的,本文分步驟結(jié)合實例代碼給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下2023-08-08
SpringBoot定制化Starter實現(xiàn)方法
小伙伴們曾經(jīng)可能都經(jīng)歷過整天寫著CURD的業(yè)務,都沒寫過一些組件相關(guān)的東西,這篇文章記錄一下SpringBoot如何自定義一個Starter。原理和理論就不用多說了,可以在網(wǎng)上找到很多關(guān)于該方面的資料,這里主要分享如何自定義2023-01-01

