1、問題描述
我寫完一個接口,在用postman測試的時候,發現其中有一個參數cEnterpriseId明明是有值的,但接口controller接收到的該參數為null,但其他參數都不為null的。
2、解決方法
我首先去百度了一下,說是由於實體類的參數命名不規范導致的,沒有按照標准“駝峰法”進行參數命名。也可以在實體類相應的參數上加上@JsonProperty(value="xxx")來解決。
解決方法一、
加@JsonProperty注解
在實體類的cEnterpriseId參數上加上@JsonProperty(value = "cEnterpriseId")就解決了。
解決方法二、
手動在實體類添加get / set方法
解決方法三、
把postman傳參的cEnterpriseId改成小寫centerpriseId
3、產生原因
我看網上不少說產生類似的問題@RequestBody獲取的參數為null是由於springboot解析器在解析json過程中出現問題,因字段名駝峰命名無法匹配字段名導致。spring框架在接收參數的時候的get()方法無法識別參數。
不過我感覺這樣子說的太籠統了,無法解答我的困惑。
后來我仔細研究了一下,簡單說一下我的看法和理解吧。
首先我在實體類CustomerUsecaseJourneyBO上加了@Data注解,@Data注解大家應該都熟悉,就是用來生成實體類的get和set方法並隱藏get/set方法的。
那么對於cEnterpriseId這個參數,@Data注解自動為它生成的get/set方法是這樣子的:
然后我用idea工具,自動在實體類中生成了一下cEnterpriseId的get/set方法。
@Data生成的是getCEnterpriseId()/setCEnterpriseId(),而idea自動生成的是getcEnterpriseId()/setcEnterpriseId()。
我用postman傳一個json到接口,json在傳輸過程中會被轉為“字節流”。接口controller層的@RequestBody加在實體類參數前面,會把接收到的字節流反序列成為一個java實體類。@RequestBody在反序列化的時候給實體類賦值使用的get/set方法是同idea自動生成的get/set方法,即:getcEnterpriseId()/setcEnterpriseId()。所以@RequestBody是用setcEnterpriseId()給是實體類CustomerUsecaseJourneyBO賦值,但在CustomerUsecaseJourneyBO類中setcEnterpriseId()是不存在的,CustomerUsecaseJourneyBO類中只有setCEnterpriseId()。
setcEnterpriseId() 不等於 setCEnterpriseId()。
當然其實也可以不加@JsonProperty注解,只需修改一下postman傳參的大小寫就行了。
把cEnterpriseId改成centerpriseId,因為centerpriseId對應的get/set方法是getcEnterpriseId()/setcEnterpriseId()。
梳理了一下,大致的流程是這樣的
關於json被@RequestBody反序列化給實體類的具體過程可以參考一下這篇:@RequestBody的使用_JustryDeng-CSDN博客_@requestbody
4、總結
@RequestBody反序列化實體類部分值為null,這個問題以前沒有碰到過,后來經研究發現竟然是參數命名不符合“駝峰法”,cEnterpriseId對應的數據庫表字段是c_enterpriseId,我的idea工具裝了阿里巴巴代碼規范檢測插件明明檢查結果是“cEnterpriseId”是一個合法的參數命名,因此是因為cEnterpriseId命名不規范導致@RequestBody反序列化set不了實體類的參數,顯然也是解釋不通的。
不過我也是第一次發現注解@Data生成的get/set方法和idea工具自動生成的get/set在命名上竟然會不一致。
不過@Data生成的get/set方法是會被覆蓋的。因此看來以后寫實體類在加@Data注解時要多留個心眼,最好在實體類中寫get/set方法,而不是通過@Data隱藏封裝get/set方法。另外如果涉及前端的json的化,最好一定要加@JsonProperty。來保證實體類中的字段與json一一對應上。
5、參考資料
- Springboot | @RequestBody 接收到的參數對象屬性為空 - 走看看
- 使用@RequestBody注解,接收不到參數,參數為NULL - 程序員大本營
- @RequestBody注解原理 - 簡書
- @RequestBody的使用_JustryDeng-CSDN博客_@requestbody
- @RequestBody和@ResponseBody和消息轉換器機制原理_Hedwig的博客-CSDN博客_requestbody 原理
- @JsonProperty使用詳解_0bug0warning的博客-CSDN博客_@jsonproperty
- 序列化和反序列化的詳解_tree_ifconfig的博客-CSDN博客_序列化和反序列化
- 什么是駝峰命名法_百度知道