SpringMVC @RequestBody出現(xiàn)400 Bad Request的解決
@RequestBody出現(xiàn)400 Bad Request的問(wèn)題
今天與同事調(diào)試一個(gè)接口,發(fā)現(xiàn)后臺(tái)使用@RequestBody老是獲取不到數(shù)據(jù)。查了網(wǎng)上很多資料,要使用@RequestBody來(lái)轉(zhuǎn)換JSON字符串為對(duì)象
大概是以下幾個(gè)點(diǎn)
1. 請(qǐng)求的Content-Type要是application/json
2. 請(qǐng)求的類(lèi)型要是POST
3. 前臺(tái)json傳遞的key在后臺(tái)的實(shí)體對(duì)象中存在,也就是JSON要與實(shí)體對(duì)象要對(duì)應(yīng),并且名稱(chēng)要一致(如果不一致可以使用@JsonProperty來(lái)做映射)
以上這些我基本都檢查過(guò)了,都沒(méi)有問(wèn)題,但是程序根本就不會(huì)進(jìn)入接口方法,詳細(xì)檢查了前端傳送到后臺(tái)確實(shí) application/json類(lèi)型的數(shù)據(jù)。
如下:
POST /quickstart/api/v1/dataSync/syncUser HTTP/1.1 Content-Length: 67 Host: 192.168.1.231:9090 Content-Type: application/json {"username": "1111","password": "e10adc3949ba59abbe56e057f20f883e"} HTTP/1.1 400 Bad Request Content-Length: 0 Server: Jetty(7.6.15.v20140411)
SpringMVC也沒(méi)有拋出任何錯(cuò)誤,于是在接口Controller加入以下異常處理代碼來(lái)確定異常信息:
@ResponseBody ?? ?@ResponseStatus(HttpStatus.BAD_REQUEST) ?? ?@ExceptionHandler(HttpMessageNotReadableException.class) ?? ?public void messageNotReadable(HttpMessageNotReadableException exception, HttpServletResponse response){ ?? ??? ?//調(diào)試作用,用來(lái)調(diào)試前臺(tái)傳遞json后臺(tái)無(wú)法正確映射問(wèn)題 ?? ??? ? ?? ??? ?logger.error("請(qǐng)求參數(shù)不匹配。", exception); ?? ? ? ? ?? ?}
終于后臺(tái)打印出錯(cuò)誤信息如下:
Caused by: com.fasterxml.jackson.databind.JsonMappingException: No content to map due to end-of-input
at [Source: org.eclipse.jetty.server.HttpInput@42f0d7f3; line: 1, column: 1]
at com.fasterxml.jackson.databind.JsonMappingException.from(JsonMappingException.java:164) ~[jackson-databind-2.4.0.jar:2.4.0]
at com.fasterxml.jackson.databind.ObjectMapper._initForReading(ObjectMapper.java:3095) ~[jackson-databind-2.4.0.jar:2.4.0]
at com.fasterxml.jackson.databind.ObjectMapper._readMapAndClose(ObjectMapper.java:3036) ~[jackson-databind-2.4.0.jar:2.4.0]
但是還是找不到問(wèn)題所在,最后無(wú)意發(fā)現(xiàn)前面有一段測(cè)試代碼(因?yàn)槌绦蛞恢睙o(wú)法進(jìn)入Controller的接口方法,所以我在Spring攔截器中加了一段代碼),測(cè)試前端傳過(guò)來(lái)的JSON數(shù)據(jù)的內(nèi)容。也就是這段代碼導(dǎo)致了這一切。
@Override ?? ?public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { ?? ??? ?BufferedReader reader = new BufferedReader(new InputStreamReader(request.getInputStream())); ?? ??? ?StringBuffer buffer = new StringBuffer(); ? ?? ??? ?String line = " "; ? ?? ??? ?while ((line = reader.readLine()) != null){ ? ?? ??? ? ? ? buffer.append(line); ? ?? ??? ?} ? ?? ??? ?System.out.println(buffer.toString());
查看文檔,發(fā)現(xiàn)HttpServletRequest.getInputStream(),一般只能被調(diào)用一次,在request.getinputstream讀取一次后position到了文件末尾,第二次就讀取不到數(shù)據(jù),由于無(wú)法reset(),所以,request.getinputstream只能讀取一次。
做了幾年程序第一次知道HttpServletRequest.getInputStream()只能被讀取一次,真是學(xué)藝不精啊。
post 400 (Bad Request)異常怎么排查參數(shù)
問(wèn)題描述
用ajax請(qǐng)求時(shí)報(bào)post 400 (Bad Request)的異常,前臺(tái)js參數(shù)JSON.stringify(data),后臺(tái)controller 中@RequestBody XX xx(javabean)接收參數(shù)。
通常發(fā)生400時(shí),即使在后臺(tái)方法上設(shè)置斷點(diǎn),但因400是參數(shù)由json轉(zhuǎn)換成Javabean時(shí)發(fā)生異常,所以不會(huì)進(jìn)入斷點(diǎn)。
此時(shí)如果單靠眼力一一排查參數(shù)中的每個(gè)值,簡(jiǎn)直能把眼瞅瞎……還未必能找到……
解決辦法
辦法一:
從大牛那取經(jīng),可以org.springframework.web.servlet.DispatcherServlet中設(shè)置斷點(diǎn),好像是doService方法,下次再遇到自己打算試試。
辦法二:
自己找到了一個(gè)low但比較簡(jiǎn)單直觀的辦法,哈哈
1.瀏覽器F12,調(diào)試狀態(tài)下在network/網(wǎng)絡(luò)找到400(Bad Request)的請(qǐng)求,復(fù)制出該post請(qǐng)求的json格式的請(qǐng)求參數(shù)。
以chrome為例,點(diǎn)擊“view source”會(huì)顯示json字符串格式的參數(shù)。
2.在后臺(tái)方法中將該json字符串轉(zhuǎn)換成JSONObject,再將JSONObject轉(zhuǎn)換成實(shí)體XX。
代碼:
com.alibaba.fastjson.JSONObject.toJavaObject( (com.alibaba.fastjson.JSONObject)(com.alibaba.fastjson.JSONObject.parse("{'ts':1493184921039,'pk':nulll}")),XX.class)
其中的{'ts':1493184921039,'pk':nulll}是請(qǐng)求參數(shù)字符串(將雙引號(hào)改成單引號(hào)),JSONObject.parse()方法將其轉(zhuǎn)換成JSONObject格式;JSONObject.toJavaObject()是轉(zhuǎn)換為實(shí)體XX的方法。
3.運(yùn)行代碼,就會(huì)報(bào)錯(cuò),錯(cuò)誤中會(huì)提示那些參數(shù)有問(wèn)題,進(jìn)而修改就可以啦。
到目前為止遇到過(guò)兩次參數(shù)的問(wèn)題,一次是時(shí)間戳ts的格式導(dǎo)致400的,當(dāng)時(shí)ts是是由net.sf.json.JSONObject處理過(guò)返回給前臺(tái)頁(yè)面的,等到再將包含該ts的實(shí)體json串傳給后臺(tái)時(shí)就因無(wú)法轉(zhuǎn)換為實(shí)體報(bào)錯(cuò)了。
第二次就是現(xiàn)在因?yàn)閷?shí)體中的一個(gè)屬性是空值,而實(shí)體類(lèi)中該屬性的set方法對(duì)該屬性值進(jìn)行了特殊處理,卻又未判空導(dǎo)致了空指針異常。
總結(jié)
以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。
- SpringMVC打印請(qǐng)求參數(shù)和響應(yīng)數(shù)據(jù)最優(yōu)方案
- SpringMVC配置javaConfig及StringHttpMessageConverter示例
- springMvc和mybatis-plus中枚舉值和字段的映射
- SpringMVC基于配置的異常處理器
- SpringMVC 異常處理機(jī)制與自定義異常處理方式
- Java SpringMVC攔截器與異常處理機(jī)制詳解分析
- Java SpringMVC 異常處理SimpleMappingExceptionResolver類(lèi)詳解
- SpringMVC空指針異常NullPointerException解決及原理解析
相關(guān)文章
使用JMX監(jiān)控Zookeeper狀態(tài)Java API
今天小編就為大家分享一篇關(guān)于使用JMX監(jiān)控Zookeeper狀態(tài)Java API,小編覺(jué)得內(nèi)容挺不錯(cuò)的,現(xiàn)在分享給大家,具有很好的參考價(jià)值,需要的朋友一起跟隨小編來(lái)看看吧2019-03-03java數(shù)組復(fù)制的四種方法效率對(duì)比
這篇文章主要介紹了java數(shù)組復(fù)制的四種方法效率對(duì)比,文中有簡(jiǎn)單的代碼示例,以及效率的比較結(jié)果,具有一定參考價(jià)值,需要的朋友可以了解下。2017-11-11深入學(xué)習(xí)java8?中的CompletableFuture
本文主要介紹了java8中的CompletableFuture,CompletableFuture實(shí)現(xiàn)了CompletionStage接口和Future接口,前者是對(duì)后者的一個(gè)擴(kuò)展,增加了異步回調(diào)、流式處理、多個(gè)Future組合處理的能力,使Java在處理多任務(wù)的協(xié)同工作時(shí)更加順暢便利,下文需要的朋友可以參考一下2022-05-05Maven腳手架如何基于jeecg實(shí)現(xiàn)快速開(kāi)發(fā)
這篇文章主要介紹了Maven腳手架如何基于jeecg實(shí)現(xiàn)快速開(kāi)發(fā),文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2020-10-10java基礎(chǔ)類(lèi)型源碼解析之多角度講HashMap
這篇文章主要給大家介紹了關(guān)于java基礎(chǔ)類(lèi)型源碼解析之HashMap的相關(guān)資料,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家學(xué)習(xí)或者使用java基具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2019-07-07詳解log4j-over-slf4j與slf4j-log4j12共存stack overflow異常分析
這篇文章主要介紹了詳解log4j-over-slf4j與slf4j-log4j12共存stack overflow異常分析,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2018-07-07基于RecyclerChart的KLine繪制Volume實(shí)現(xiàn)詳解
這篇文章主要為大家介紹了基于RecyclerChart的KLine繪制Volume實(shí)現(xiàn)詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-03-03基于Java解決華為機(jī)試實(shí)現(xiàn)整數(shù)與IP地址間的轉(zhuǎn)換?
這篇文章主要介紹了基于Java解決華為機(jī)試實(shí)現(xiàn)整數(shù)與IP地址間的轉(zhuǎn)換,文章舉例說(shuō)明圍繞文章主題展開(kāi)相關(guān)內(nèi)容,具有一定的參考價(jià)值,需要的小伙伴可以參考一下2022-02-02