一次SpringBoot版本升級,引發的血案

前言

最近項目組升級了SpringBoot版本,由之前的2.0.4升級到最新版本2.7.5,卻引出了一個大Bug。

到底是怎麼回事呢?

1.案發現場

有一天,項目組的同事反饋給我說,我之前有個接口在新的測試環境報錯了,具體異常是:Missing argment level for method parameter of type Integer

我當時的第一反應有點懵,心想這個接口是一個老接口,有一年多的時間都沒改過了,怎麼會出問題呢?

他說近期另外一個同事為了部署阿里雲服務器,把新測試環境SpringBoot的版本升級到了最新版

之後,在測試的過程中,發現我有個Get請求接口報異常了。

該接口代碼類似於這樣:

在getCategory接口中,有兩個參數:

  1. type表示大類,是必傳的。
  2. level表示要返回幾級分類,比如:4級分類,就傳4,是非必傳的,默認就是查4級分類。

就是這樣一個接口的level參數,前端沒有傳參,例如:


結果被Spring MVC攔截直接報錯了。

2 報錯的原因

從打印的異常信息看,現在level參數必須要傳值了,之前是可傳,可不傳的。

我後來本打算自定義Spring的轉換器,修改一下校驗規則,跟老版本保持一致。

這樣那些基本接口就不用改了。

但後來發現,被spring-web-5.3.23的源碼無情的打臉了。

org.springframework.web.method.annotation包下的AbstractNamedValueMethodArgumentResolver類的resolveArgument方法中:

多了這樣的校驗。如果該參數為空,沒有設置默認值,required屬性為true,並且不是Optional類型,則執行handleMissingValueAfterConversion方法。

該方法會調用handleMissingValue方法,具體代碼如圖中所示:

最後會拋出之前我看到的那個異常。

原因最新版本的Spring中不允許Get接口的請求參數,在不使用@RequestParam註解時,值為空的情況出現了。

3 如何解決問題?

想要解決上面的報錯問題,其實很簡單,只需在level參數前加@RequestParam註解,並且設置required屬性為false

例如:

但是後面發現,項目中不只我這一個接口要調整,其他好多同事的接口,也有類似的問題,需要修改的接口很多。

這個改動的工作量不小。

哭暈在測試。。。

後話

很多人中招,所以非常有必要把這個問題分享給大家,防微杜漸。

我之前level參數不加@RequestParam註解,也沒設置required屬性,當時持有的心態是Spring有默認值,有些註解不加程序也能正常運行,既然這樣就可以少寫點代碼,並且在當時的版本測試過,沒有出現過什麼問題。

這種情況其實是Spring框架的一個bug,已經在最新版本中被修復了。。。

趕緊review一下你們的代碼,看看有沒有類似的用法,不然遲早有一天也會中招。