axios利用params/data發送參數給springboot controlle的正確獲取方式

引言

今天有人遇到接口調用不通的情況,粗略看瞭一下是axios跨域請求引起瞭。找到問題,處理就簡單多瞭。

但是我看其代碼,發現比較有意思

export function agentlist(query) {
  return request({
    url: /agent/list',
    method: 'get',
    params: query
  })
}
export function editagent(data) {
    return request({
        url: '/agent/editagent',
        method: 'post',
        data:data
    })
}
export function deleteagent(id) {
    return request({
        url: '/agent/delete',
        method: 'post',
        params:{id}
    })
}

上面的代碼中的request是axios實例,同是post卻出現瞭data或params做數載體的情況。憑直覺該代碼會在後續請求中出現問題,果不其然後續出現各種問題。

出現的問題主要是:前端傳遞參數給瞭springboot程序,但是程序中卻接收不到數據或隻接收到部分數據。出現問題前後端代碼如下:

前端:

export function login(account, password, orgType) {
  return request({
    url: '/webapi/login',
    method: 'post',
    data: {"loginId":account,"password":password,"orgType":orgType}
)}

後端:

@PostMapping(value = "/login")
public Result login(String loginId, String password, int orgType, HttpServletResponse response){
}

程序運行異常:

java.lang.IllegalStateException: Optional int parameter 'orgType' is present but cannot be translated into a null value due to being declared as a primitive type. Consider declaring it as object wrapper for the corresponding primitive type.

問題分析:

出現異常的原因看似orgType無法轉換為對象類型引發的,真實情況並非如此。真正的原因是Java中的代碼根本就無法獲取到3個參數,前兩個是String類型在無法獲取參數的情況下會被賦值為null,第三個參數因是 int 類型,因無法賦值為null,故引發該異常。出現異常並非Java代碼寫得不好,而是前後臺傳參銜接出瞭問題。

前端數據發送網絡請求,註意下面的數據的格式:

前端數據確實發送瞭,但是數據的格式為json格式。

服務器端POST請求獲取參數,要求的參數格式為:key=value&key2=value2&key…..,因此服務器端無法獲取數據也就好理解瞭。

解決上述解決方案:

前端解決方案1

export function login(account, password, orgType) {return request({
    url: '/webapi/login',
    method: 'post',
    data: "loginId="+account+ "&password="+password+"&orgType="+orgType
  })
}

手動構造服務器端需要的數據格式,此時再次執行客戶端程序,並跟蹤網絡請求如下圖,springboot程序正常獲取到數據。

上面這種方案雖能解決問題,但太機械,用來分析問題可以,生產中就行不通瞭。

前端方案2

export function login(account, password, orgType) {
  return request({
    url: '/webapi/login',
    method: 'post',
    params: {"loginId":account, "password":password,"orgType":orgType} 
  })
}

將 axios 中的參數載體由 data 改為 params,此時再次執行客戶端程序,並跟蹤網絡請求如下圖,springboot程序正常獲取到數據。

上面這種解決方案,將要發送的數據對象以params做載體發送時,axios會把數據對象的屬性與值拼成 k=v&k=v 格式,但這些數據是作為 Query String(放在url中的參數) 傳遞給後臺程序的,因此並非真正意義上post傳參(實際是post方式向增加瞭參數url地址,提交空數據😀)。

總結:通過上面的兩個前端解決方案,現在就很容易搞清楚 axios 中的 params與data 傳參的區別瞭。

params 傳參,參數以 k=v&k=v 格式放置在 url 中傳遞。

data傳參,參數會收到Request Header中的 Content-Type 類型的影響,但它們肯定不會出現在url中,我們就暫且任務 data 的參數會在 form表單中吧。

前端解決方案3

使用 qs 來實現 json 對象的 k=v 格式化

import qs form 'qs'

export function login(account, password, orgType) {
  return request({
    url: '/webapi/login',
    method: 'post',
    data: qs.stringify({"loginId":account, "password":password,"orgType":orgType})
  })
}

如此一來,就非常方便的將json對象序列化為url格式,json對象屬性再多也不再是負擔。

現在 json 當紅,js模塊化…..超速發展,我們的項目中再傳一個兩個的參數太low,現在流行傳對象。要前端傳遞對象到後端 springboot web 程序,現在這都是事兒。

前端傳遞json對象到springboot web 程序

1、在前端使用 data 作為載體傳遞 json 對象

var jsonObject = {"loginId":account, "password":password,"orgType":orgType};


export function login(obj) {
  return request({
    url: '/webapi/login',
    method: 'post',
    data: obj
  })
}

login(jsonObject);

2、Springboot後端

class LoginModel{ 
    String loginId,passowrd;

    public String getLoginId() {
        return loginId;
    }

    public void setLoginId(String loginId) {
        this.loginId = loginId;
    }

    public String getPassowrd() {
        return passowrd;
    }

    public void setPassowrd(String passowrd) {
        this.passowrd = passowrd;
    }

    public Integer getOrgType() {
        return orgType;
    }

    public void setOrgType(Integer orgType) {
        this.orgType = orgType;
    }

    Integer orgType;
    
}

    @PostMapping(value = "/login")
    public Result login(@RequestBody LoginModel model, HttpServletResponse response){}

springboot web端,通過@RequestBody註解將自動收集請求的 payload 中的數據,並將數據反序列化為 LoginModel對象。

簡單總結一下 springboot中關於 @RequsetParam、@RequestBody與不加註解獲取參數的區別

1、@RequsetParam 獲取 k=v 格式的參數,get/post都可以

2、@RequestBody 獲取payload中的數據,對於前端傳遞的 json 對象在 springboot web中反序列化尤為方便,同時它還支持獲取二進制字節數據等。

3、在不適用註解獲取參數時,默認@RequsetParam機制,並且要求前端傳遞的參數名稱與springboot web 在的參數名稱一致,否則無法獲取到數據。

最後在說明一點,用於反序列化的 Java 類,最好不要使用 java基本數據類型,盡量使用 基本類型的包裝類型,如上面LoginModel中的 Integer,這樣就可以在前端不傳對應參數時保持為null👌

總結

到此這篇關於axios利用params/data發送參數給springboot controlle的正確獲取方式的文章就介紹到這瞭,更多相關axios用params/data發送參數內容請搜索WalkonNet以前的文章或繼續瀏覽下面的相關文章希望大傢以後多多支持WalkonNet!

推薦閱讀: