springmvc
前幾天朋友找我,說遇到一個(gè)問題,在使用springboot開發(fā)的時(shí)候,json數(shù)據(jù)傳值但是后臺(tái)model映射不上,問我有沒有遇到這個(gè)問題。因?yàn)榭吹讲坏皆创a,只能靠猜測。便猜測了幾個(gè)原因??墒悄?都不對。
最后告訴我是被攔截器攔截了,突然意識到應(yīng)該是body中的流被消費(fèi)了。
攔截器呢是這么寫的。

后臺(tái)采用下圖的接收方式:

便讓我給分析下原因,正好有時(shí)間,我就還原了一下現(xiàn)場。
順便考慮下解決方案,代碼上傳到了github: https://github.com/topyuluo/question
先說第一個(gè)問題吧:攔截器中通過request.getInputStream()消費(fèi)了流中的數(shù)據(jù),而@RequestBody只能以流的方式讀取,流被讀過一次后,就不存在了,會(huì)導(dǎo)致后續(xù)無法處理。后臺(tái)會(huì)拋出此異常:
java.io.IOException: Stream closed
從網(wǎng)上找了一張圖,先看下springmvc的工作流程:

上圖是springmvc的整個(gè)執(zhí)行流程。已經(jīng)很清楚了,就不贅述了。
下面從源碼的層級來看下此異常的出處,先說一下異常產(chǎn)生的原因,我畫了一張圖。

@RequestBody ,是從InputStream中取值
@RequestParam ,是利用request.getParameterValues()來取值
解決方案:
既然找到了原因,對癥下藥就可以了,由于我們消費(fèi)了流,導(dǎo)致了流關(guān)閉,那么如果能將流拷貝一份或者向后臺(tái)在傳一份一模一樣的是否就解決了呢。
由于攔截器的特點(diǎn)不能實(shí)現(xiàn)這個(gè)需求,所以將攔截器替換為過濾器。
主要代碼如下:
request包裝類

response包裝類:

注冊過濾器:

過濾器中使用:

這樣就可以在controller中使用@RequestBody接收了。