spring學習歷篇二:@RequestParam和@RequestBody與前端Get和Post請求傳參詳解附中文亂碼解決方法

1.先入爲主:

1.在spring的controller中,寫法必須是同一個請求中只能有一個@RequestBody;同一個請求中,可以有多個@RequestParam;同一個請求可以同時存在@RequestBody和@RequestParam;


2.請求中@RequestParam()指定的參數可以是普通元素、數組、集合等等;當@RequestBody 與@RequestParam()同時使用時,原SpringMVC接收參數的機制不變,RequestBody接收的是請求體裏面的數據;而RequestParam接收的是請求行中key-value參數它會被springMVC的切面進行處理從而可以用普通元素、數組、集合、對象等接收;如果參數是放在請求體中,傳入後臺的話,那麼後臺要用@RequestBody才能接收到;如果參數放在請求行以?key=value形式傳遞則要用@RequestParam來接收,或則形參不加@RequestParam註解也能接收。
例:
@RequestParam() String xx:前端xx=StringValue
@RequestParam() int xx:前端xx=intValue
@RequestParam() Integer xx:前端xx=intValue
@RequestParam() double xx:前端xx=10.12
@RequestParam() boolean xx:前端xx=true false
@RequestParam() Map xx:前端xx={k1=12,ssd="sd"}
@RequestParam() List xx:前端xx={k1=12,ssd="sd00"},{k1=1223,ssd="sd11"}.......


3.如果參數前指定註解@RequestParam(xxx),那麼前端請求行中必須有對應的xxx名字纔行(不管其是否有值,也可以通
過設置該註解的required屬性來調節是否必須傳),如果沒有xxx名的話,那麼請求會出錯,報400。    

4.如果參數前不指定註解@RequestParam(xxx)的話,那麼就前端請求行中可以有也可以沒有對應的xxx名字,如果有xxx名
的話,那麼就會自動匹配;沒有的話,請求也能正確發送。

5.如果參數指定註解@RequestBody,且參數是一個POJO對象或Map<String,Object>,那麼,請求頭必須設置application/json且前端請求體數據格式的字段必須與POJO一致否則報錯400,如果請求體中某個字段value沒有值,那麼可以不寫入請求體的json中。

2.實驗過程:

http請求規範說明:
常規操作下,Get在
請求行以?key=value形式傳遞參數(value可以是:[1,2,3],{a=s,k=oom,p="x"},{as:"xx",moo:00}等等);Post請求在請求體傳遞參數(string、json均可)。而經測試,Get其實也可以在請求體中傳遞參數的,但由於可能存在某些情況
下服務器不支持,如:緩存代理服務器。因此,我們通常在請求體中傳遞參數還是會使用Post請求方式。

上述引申的兩個概念(請求行和請求體)請自行問度娘。

因此,下面的實驗場景Get方式均不在請求體中傳參。而post方式可在請求行也可在請求體傳參。(牢記!)


前後端處理請求的各個場景:


場景1:


後臺:
@ResponseBody
public String testAny1(String token)

請求:
get無參數訪問:訪問正常,響應正常,接收參數token爲null
post無參數訪問:訪問正常,響應正常,接收參數token爲null
get傳參訪問,請求行?token=xxx訪問:訪問正常,響應正常,接收參數token正常
post傳參訪問,請求行參數?token=xxx訪問:訪問正常,響應正常,接收參數token正常
post傳參訪問,請求體參數token訪問:訪問正常,響應正常,接收參數token爲null
post傳參訪問,請求體參數{token:xxx}訪問:訪問正常,響應正常,接收參數token爲null


正確使用小結:參數未指定任何註解時,請求使用Get或Post均可,token必須在請求行以?token=xx方式傳遞才能獲取到,若不傳遞token參數不會報錯。
注意:請求頭使用默認即可,若設置其他請求頭也不會報錯

場景2:


後臺:
@ResponseBody
public String testAny2(@RequestParam String token)

請求:
get無參數訪問:報錯400,(HTTP Status 400 - Required String parameter 'token' is not present)
post無參數訪問:報錯400,(HTTP Status 400 - Required String parameter 'token' is not present)
get傳參訪問,請求行?token=xxx訪問:訪問正常,響應正常,接收參數token正常
post傳參訪問,請求行參數?token=xxx訪問:訪問正常,響應正常,接收參數token正常
post傳參訪問,請求體參數token訪問:報錯400,(HTTP Status 400 - Required String parameter 'token' is not present)
post傳參訪問,請求體參數{token:xxx}訪問:報錯400,(HTTP Status 400 - Required String parameter 'token' is not present)

正確使用小結:參數指定@RequestParam註解時,請求使用Get或Post均可,token必須傳遞且在請求行以?token=xx方式傳遞纔不會報錯且後臺才能獲取到。
注意:請求頭使用默認即可,若設置其他請求頭也不會報錯

場景3:


後臺:
@ResponseBody
public String testAny3(@RequestParam("token") String token)

請求:
get無參數訪問:報錯400,(HTTP Status 400 - Required String parameter 'token' is not present)
post無參數訪問:報錯400,(HTTP Status 400 - Required String parameter 'token' is not present)
get傳參訪問,請求行?token=xxx訪問:訪問正常,響應正常,接收參數token正常
post傳參訪問,請求行參數?token=xxx訪問:訪問正常,響應正常,接收參數token正常
post傳參訪問,請求體參數token訪問:報錯400,(HTTP Status 400 - Required String parameter 'token' is not present)
post傳參訪問,請求體參數{token:xxx}訪問:報錯400,(HTTP Status 400 - Required String parameter 'token' is not present)

正確使用小結:參數指定@RequestParam("token")註解時,請求使用Get或Post均可,token必須傳遞且在請求行以?token=xx方式傳遞纔不會報錯且後臺才能獲取到。
注意:請求頭使用默認即可,若設置其他請求頭也不會報錯

場景4:


後臺:
@ResponseBody
public String testAny4(@RequestBody String params)

請求:
get無參數訪問:訪問正常,響應正常,接收參數params爲""
post無參數訪問:訪問正常,響應正常,接收參數params爲""
get傳參訪問,請求行?params=xxx訪問:訪問正常,響應正常,接收參數爲""
post傳參訪問,請求行?params=xxx訪問:訪問正常,響應正常,接收參數爲""
post傳參訪問,請求體參數params(String)訪問:訪問正常,響應正常,接收參數爲String值
post傳參訪問,請求體參數params(json)訪問:訪問正常,響應正常,接收參數爲jsonString值

設置請求頭Content-Type:application/json,報錯:報錯400,The request sent by the client was syntactically incorrect.
這裏使用使用text請求頭或默認請求頭

正確使用小結:參數指定@RequestBody註解時,請求使用Get或Post均可,params必須在請求體傳遞後臺才能獲取到。(推薦post方式發送帶有請求體參數請求)
注意:請求頭使用默認即可,若設置Content-Type:application/json或Content-Type:text/html請求頭會報錯400,設置爲其餘請求頭不會報錯。

場景5:


後臺:
@ResponseBody
public RequestPagination testAny5(@RequestBody RequestPagination params)

請求:
get無參數訪問:肯定報錯415或400,
post無參數訪問:肯定報錯415或400,
get傳參訪問,請求行?params=xxx訪問:肯定報錯415或400,
post傳參訪問,請求行?params=xxx訪問:肯定報錯415或400,
post傳參訪問,請求體參數params(String)訪問:肯定報錯415或400,
post傳參訪問,請求體參數params(json)訪問:可能報錯415或400,

未設置請求頭Content-Type:application/json:報錯415,The server refused this request because the request entity is in a format not supported by the requested resource for the requested method
設置請求頭Content-Type:application/json,但不在請求體傳參或傳參格式不正確則報錯:報錯400,The request sent by the client was syntactically incorrect.

請求頭Content-Type:application/json,設置後,在請求體傳入正確格式json(字段與RequestPagination字段對應)才能訪問正常,響應正常且參數接收正常。

正確使用小結:參數指定@RequestBody註解且參數爲pojo對象時,請求使用Get或Post均可,params必須在請求體並且以json形式保持字段與後臺參數pojo對象字段一致,纔不會報錯後臺才能獲取到。(推薦post方式發送帶有請求體參數請求)。如果請求體中某個字段value沒有值,那麼可以不寫入請求體的json中。
注意:請求頭使用Content-Type:application/json,若設置其他請求頭會報錯415。

場景6:


後臺:
@ResponseBody
public String testAny6(@RequestBody String params,@RequestParam("token") String token)

請求:
設置請求頭Content-Type:application/json:
get無參數訪問:肯定報錯400,The request sent by the client was syntactically incorrect
post無參數訪問:肯定報錯400,The request sent by the client was syntactically incorrect
get傳參訪問,請求行?params=xxx訪問:肯定報錯400,The request sent by the client was syntactically incorrect
post傳參訪問,請求行?params=xxx訪問:肯定報錯400,The request sent by the client was syntactically incorrect
post傳參訪問,請求體參數params(String)訪問:肯定報錯400,The request sent by the client was syntactically incorrect
post傳參訪問,請求體參數params(json)訪問:肯定報錯400,The request sent by the client was syntactically incorrect

設置請求頭Content-Type:text 或 Content-Type:text/plain 或 默認:
get無參數訪問:HTTP Status 400 - Required String parameter 'token' is not present,
post無參數訪問:HTTP Status 400 - Required String parameter 'token' is not present
get傳參訪問,請求行?token=xxx&params=xx訪問:正常訪問、響應、接收參數params爲""
post傳參訪問,請求行?token=xxx&params=xxx訪問:正常訪問、響應、接收參數params爲""
post傳參訪問,請求體參數params(String)且請求行參數token=xxx訪問:正常訪問、響應、接收參數正常。
post傳參訪問,請求體參數params(json)且請求行參數token=xxx訪問:正常訪問、響應、接收參數正常。


正確使用小結:同時存在參數指定@RequestBody註解,和參數指定@RequestParam("xxx")註解時候,請求使用Get或Post均可,params必須在請求體傳遞並且在請求行以?token=xx傳遞,纔不會報錯後臺才能獲取到兩參數。(推薦post方式發送帶有請求體參數請求)
注意:請求頭使用默認即可,若設置Content-Type:application/json或Content-Type:text/html請求頭會報錯400,設置爲其餘請求頭不會報錯。

場景7:


後臺:
@ResponseBody
public String testAny7(@RequestBody RequestPagination params,@RequestParam("token") String token)

請求:
設置請求頭Content-Type:application/json:
get無參數訪問:肯定報錯400,The request sent by the client was syntactically incorrect
post無參數訪問:肯定報錯400,The request sent by the client was syntactically incorrect
get傳參訪問,請求行?params=xxx訪問:肯定報錯400,The request sent by the client was syntactically incorrect
post傳參訪問,請求行?params=xxx訪問:肯定報錯400,The request sent by the client was syntactically incorrect
post傳參訪問,請求體參數params(String)訪問:肯定報錯400,The request sent by the client was syntactically incorrect
post傳參訪問,請求體參數params(json)訪問:肯定報錯400,The request sent by the client was syntactically incorrect
post傳參訪問,請求體參數params(json且字段與RequestPagination字段對應),且請求行參數token=xxx訪問才能訪問正常,響應正常且參數接收正常。


設置請求頭Content-Type:text 或 Content-Type:text/plain 或 默認:
get無參數訪問:415,The server refused this request because the request entity is in a format not supported by the requested resource for the requested method
post無參數訪問:同上
get傳參訪問,請求行?token=xxx&params=xx訪問:同上
post傳參訪問,請求行?token=xxx&params=xxx訪問:同上
post傳參訪問,請求體參數params(String)且請求行參數token=xxx訪問:同上
post傳參訪問,請求體參數params(json)且請求行參數token=xxx訪問:同上


正確使用小結:同時存在參數指定@RequestBody註解且爲pojo對象,和參數指定@RequestParam("xxx")註解時候,請求使用Get或Post均可,params必須在請求體並且以json形式保持字段與後臺參數pojo對象字段一致並且在請求行以?token=xx傳遞,纔不會報錯後臺才能獲取到兩參數。(推薦post方式發送帶有請求體參數請求)。如果請求體中某個字段value沒有值,那麼可以不寫入請求體的json中。
注意:請求頭使用Content-Type:application/json,若設置其他請求頭會報錯415。

場景8:


後臺:
@ResponseBody
public String testAny8(@RequestBody String params,String token)

請求:
設置請求頭Content-Type:application/json:
get無參數訪問:肯定報錯400,The request sent by the client was syntactically incorrect
post無參數訪問:肯定報錯400,The request sent by the client was syntactically incorrect
get傳參訪問,請求行?params=xxx訪問:肯定報錯400,The request sent by the client was syntactically incorrect
post傳參訪問,請求行?params=xxx訪問:肯定報錯400,The request sent by the client was syntactically incorrect
post傳參訪問,請求體參數params(String)訪問:肯定報錯400,The request sent by the client was syntactically incorrect
post傳參訪問,請求體參數params(json)訪問:肯定報錯400,The request sent by the client was syntactically incorrect
post傳參訪問,請求體參數params(json),且請求行參數token=xxx訪問:肯定報錯400,The request sent by the client was syntactically incorrect


設置請求頭Content-Type:text 或 Content-Type:text/plain 或 默認:
get無參數訪問:請求訪問正常、響應正常。
post無參數訪問:請求訪問正常、響應正常。
get傳參訪問,請求行?token=xxx&params=xx訪問:請求訪問正常、響應正常,token接收正常,params接收爲""
post傳參訪問,請求行?token=xxx&params=xxx訪問:請求訪問正常、響應正常,token接收正常,params接收爲""
post傳參訪問,請求體參數params(String或json)訪問:請求訪問正常、響應正常,token接收爲null,params接收正常
post傳參訪問,請求體參數params(String或json)且請求行參數token=xxx訪問:請求訪問正常、響應正常,token接收爲正常,params接收正常

正確使用小結:同時存在參數指定@RequestBody註解,和參數指定token時候,請求使用Get或Post均可,params必須在請求體傳遞而在請求行中傳遞?token=xx,才能獲取到兩參數。(推薦post方式發送帶有請求體參數請求),這裏值得留意的是?token=xx也可以不傳遞,不會報錯。
注意:請求頭使用默認即可,若設置Content-Type:application/json或Content-Type:text/html請求頭會報錯400,設置爲其餘請求頭不會報錯。

場景9:


後臺:
@ResponseBody
public String testAny9(@RequestBody String params,@RequestParam String token)

請求:    
設置請求頭Content-Type:application/json:
get無參數訪問:肯定報錯400,The request sent by the client was syntactically incorrect
post無參數訪問:肯定報錯400,The request sent by the client was syntactically incorrect
get傳參訪問,請求行?params=xxx訪問:肯定報錯400,The request sent by the client was syntactically incorrect
post傳參訪問,請求行?params=xxx訪問:肯定報錯400,The request sent by the client was syntactically incorrect
post傳參訪問,請求體參數params(String)訪問:肯定報錯400,The request sent by the client was syntactically incorrect
post傳參訪問,請求體參數params(json)訪問:肯定報錯400,The request sent by the client was syntactically incorrect
post傳參訪問,請求體參數params(json),且請求行參數token=xxx訪問:肯定報錯400,The request sent by the client was syntactically incorrect


設置請求頭Content-Type:text 或 Content-Type:text/plain 或 默認:
get無參數訪問:HTTP Status 400 - Required String parameter 'token' is not present
post無參數訪問:HTTP Status 400 - Required String parameter 'token' is not present
get傳參訪問,請求行?token=xxx&params=xx訪問:請求訪問正常、響應正常,token接收正常,params接收爲""
post傳參訪問,請求行?token=xxx&params=xxx訪問:請求訪問正常、響應正常,token接收正常,params接收爲""
post傳參訪問,請求體參數params(String或json)訪問:HTTP Status 400 - Required String parameter 'token' is not present
post傳參訪問,請求體參數params(String或json)且請求行參數token=xxx訪問:請求訪問正常、響應正常,token接收爲正常,params接收正常

正確使用小結:同時存在參數指定@RequestBody註解,和參數指定token時候,請求使用Get或Post均可,params必須在請求體傳遞而在請求行中傳遞?token=xx,才能獲取到兩參數。(推薦post方式發送帶有請求體參數請求)。
注意:請求頭使用默認即可,若設置Content-Type:application/json或Content-Type:text/html請求頭會報錯400,設置爲其餘請求頭不會報錯。

 

3.補充說明響應返回場景

場景1:String + @ResponseBody

@ResponseBody
public String testAny9()

將以字符串String形式傳給HttpServletResponse返回給前端

 

場景2:對象 + @ResponseBody

@ResponseBody
public User testAny9()

先自動轉換成JSON形式傳給HttpServletResponse返回給前端,json對象

場景3:String
public String testAny9()

尋找視圖進行跳轉

場景4:void + request+response
public String testAny9(HttpServletRequest request,HttpServletResponse response)

方法體中將使用request獲取參數、response跳轉或輸出數據給前端

場景5:ModelAndView

public ModelAndView(){

    List<String> dataList = new ArrayList<String>(); 
    ModelAndView modelAndView = new ModelAndView();
    //將數據放入modelAndView對象
    modelAndView.addObject("dataList", dataList);
    //將返回的邏輯視圖名稱放入modelAndView對象
    modelAndView.setViewName("home");

    return modelAndView;
}

前端通過request.getAttribute("dataList")或${dataList}獲取傳遞的數據

 

 

總結

400錯誤:參數格式不對,例如:{id:"dds"} 正解:{"id":"dds"};例如:後臺封裝的對象沒有參數中的字段等等。

406錯誤:後臺返回給前端的是對象而非字符串,需配置下json的轉換。

 

4.中文亂碼問題


後臺代碼:
@RequestMapping(value = "/demo1")
@ResponseBody
public String demo1(){
    return "我是中文測試";
}

就是這樣一個簡單的方法,直接返回字符串, 但是在界面上就發現中文亂碼了,配置文件中<mvc:annotation-driven/>的形式開啓的.

其實這個,也不涉及到Json字符串的亂碼問題,因爲沒有使用到json的HttpMessageConverter.

 
解決方案一:

<mvc:annotation-driven conversion-service="conversionService">
    <mvc:message-converters register-defaults="true">
        <bean class="org.springframework.http.converter.StringHttpMessageConverter">
            <property name="defaultCharset" value="UTF-8"/>
            <property name="writeAcceptCharset" value="false"/>
        </bean>
    </mvc:message-converters>
</mvc:annotation-driven>

說明:替換其中的StringHttpMessageConverter,它是用來將String寫到response中;

修改的兩個屬性說明:defaultCharset改爲UTF-8(項目字符集)即可正確顯示中文,因爲默認是ISO-8859-1格式;

writeAcceptCharset修改爲false,即可看到響應頭清爽很多,節省資源;

 
解決方案二:

@RequestMapping(value = "/demo1",produces = {"text/plain;charset=utf-8","text/html;charset=utf-8"})
    @ResponseBody
    public String demo1(){
        return "我是中文測試";
    }

說明:指定響應的字符集爲utf-8,就不會再用StringHttpMessageConverter的字符集了;

 
解決方案三:

@RequestMapping(value = "/demo1",produces = {"application/json;charset=utf-8"})
@ResponseBody
public String demo1() throws JsonProcessingException {
    return new ObjectMapper().writeValueAsString("我是中文測試");
}

說明:自己轉換成JSON寫回客戶端,因爲返回值類型還是寫的String,所以仍然使用的是StringHttpMessageConverter,
但是return  “我是中文測試” ; 這個返回值不是JSON類型的,
客戶端無法解析(即使指定了produces也沒用);所以需要我們手動轉換成JSON格式字符串,這樣客戶端接收到的就是JSON格式的響應了.

 
 
比較說明:
解決方案一、二返回給瀏覽器的類型都是text/plain或 text/html類型的文本,
而解決方案三返回的是application/json類型,但是返回結果也不是JSON,所以在我看來三種方式區別都不大吧。

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章