axios傳遞參數傳不過去,前端通過axios發送post請求 后端java無法拿到數據
場景描述:
如(ru)果后端是(shi) Java(springmvc),前端使用(yong)(yong) jQuery 的 $.ajax 發(fa)送 POST 請求,測試接口是(shi)沒(mei)問題的。但是(shi)換做(zuo)使用(yong)(yong) axios 來發(fa)送 POST 請求,后端卻無(wu)法(fa)獲取(qu)數據。
問題的主要原因是后端默認接收的 POST 請求頭是 Content-Type 設置為
application/x-www-form-urlencoded 的表單請求,參數形式是 key1=value1&key2=value2 這種形式,后端獲取使用 @RequestParam 。jQuery 默認的就是這種請求方式,所以使用 $.ajax 發送請求沒有問題。
而如果發送 POST 請求時不指定請求頭 Request Header,默(mo)認(ren)使用的 Content-Type 是 text/plain;charset=UTF-8 或者(zhe) application/json ,參數(shu)出現(xian)在 Request payload 塊,其參數(shu)形(xing)式(shi)是標準的 Json 格式(shi),所以后臺還是使用 @RequestParam 就無法獲取(qu)到參數(shu),就需要改用 @RequestBody 獲取(qu)。
在 axios 中(zhong)使用(yong) POST 發送數(shu)據時,默(mo)認是直接把 Json 放到請求(qiu)體(ti)中(zhong)提交到后端(duan)的,屬于上(shang)述的第二種方式。
后端解決方案(an)
在請(qing)求參數使用 @RequestBody 注解替(ti)代 @RequestParam:
@ResponseBody@RequestMapping(value="/save",method=RequestMethod.POST) public Map<String, String> save(@RequestBody Student student)
前(qian)端(duan)解決方案:
如果后臺處理不了的話,其實這個問題(ti)前端同(tong)學完全可以自己(ji)解決的,其實就是設置請(qing)求頭而已,以下給出三種方案:
第(di)一種解(jie)決方案、前端添加請(qing)求頭(tou)信息,并重新封裝請(qing)求參數:
const params = 'username=' + this.username + '&userpass=' + this.userpass axios({ url: '/api', method: 'POST', headers: { 'content-type': 'application/x-www-form-urlencoded' }, data: params })
第(di)二種解決(jue)方案(an)、針對第(di)一種方案(an)手動拼接參數很麻煩(fan):
const params = new URLSearchParams()params.append('username', this.username)params.append('userpass', this.userpass) axios({ url: '/api', method: 'POST', headers: { 'content-type': 'application/x-www-form-urlencoded' }, data: params})
第(di)三(san)種解決方案、利用(yong)內置 qs 模塊序(xu)列化參數:
import qs from 'qs'const data = { username: this.username, userpass: this.userpass } axios({ url: '/api', method: 'POST', headers: { 'content-type': 'application/x-www-form-urlencoded' }, data: qs.stringify(data) })
當然最好的(de)方(fang)式是直(zhi)接(jie)二次封裝 axios:
// 對 axios 進行二次封裝import axios from 'axios'import qs from 'qs' // 引入 qs 模塊,該模塊不需要安裝,用來序列化 post 類型的數據// 添加一個新的 axios 的實例const http = axios.create({ baseURL: '/api', // 統一設置請求地址前綴 timeout: 6000, // 請求超時時間 withCredentials: true // 是否允許帶 cookie })// 請求攔截,統一在這里處理 POST 數據或者請求時帶上 tokenhttp.interceptors.request.use(function (config) { if (config.method === "post") { // 這一步主要取決于后端是否可以接受 json config.headers = { 'Content-Type':'application/x-www-form-urlencoded' } // 參數序列化 config.data = qs.stringify(config.data); } // 獲取 token const token = sessionStorage.getItem('token') if(token) { // ... } return config; }, function (error) { return Promise.reject(error) });// 響應攔截,處理錯誤, 如 token 不合法http.interceptors.response.use(function (response) { // ... return response; }, function (error) { // ... return Promise.reject(error) })export default http
這(zhe)樣(yang)前端(duan)請(qing)求(qiu)(qiu)還是按照原來的寫法直接(jie)給 data 傳遞對象即可,因(yin)為每次請(qing)求(qiu)(qiu)的時候都會自動轉換參數形式。
【喜歡我的文章(zhang)歡迎(ying) 轉發 點贊 與(yu) 關注(zhu),我會經常與(yu)大(da)家(jia)分(fen)享前端(duan)的知識點的】