lombok 的bug?lombok 导致 springmvc 使用 @RequestBody注解 接收 json数据 对象参数绑定失败
大家好,我是烤鴨:
?? ?lombok 導致 springmvc 使用 @RequestBody注解 接收 json數(shù)據(jù) 對象參數(shù)綁定失敗。
?? ?環(huán)境版本:
?? ??? ?spring 5.x
1. 場景復現(xiàn)
?? ?問題出現(xiàn)在創(chuàng)建對象的屬性名稱。比如我有一個類中的屬性值是?
?? ?String aTest;
?? ?首字母小寫,第二個字母大寫。
?? ?lombok 生成的get/set 方法是 getATest/setATest。
?? ?而依據(jù)java的規(guī)范(用各種ide生成的get/set方法) 應該是 getaTest/setaTest。
2. 問題猜測
? ? lombok 生成的方法不符合 JavaBean get/set 規(guī)范,導致mvc 無法封裝進入對象。
?? ?嘗試 form表單提交的方式 是沒有問題的。
?? ?問題在于json 的方式。或者說在于json序列化和反序列化時。
?? ?spring json的包 默認使用的 com.fasterxml.jackson
?? ?可以看一下 com.fasterxml.jackson.databind.deser.impl.BeanPropertyMap
?? ?的 _findWithAlias 方法,如圖:
?? ?BeanPropertyMap 獲取到類中的屬性是 atest,而前臺傳入的key是 aTest,無法匹配。
?? ?將 前臺傳參改為
? 就可以匹配上了。
3.解決
?? ?不使用lombok 或者 重寫 get/set方法。
?? ?或者 不使用 com.fasterxml.jackson 序列化,使用 fastjson。
? ? 看下有人提出過issue,而作者也提出了解決辦法。
?? ?https://github.com/rzwitserloot/lombok/issues/1661
? ??
? ??
4.深入源碼看一下
?? ?首先分析一下 com.fasterxml.jackson。
? ??org.springframework.web.servlet.mvc.method.annotation.AbstractMessageConverterMethodArgumentResolver
? ??
protected <T> Object readWithMessageConverters(HttpInputMessage inputMessage, MethodParameter parameter,Type targetType) throws IOException, HttpMediaTypeNotSupportedException, HttpMessageNotReadableException {// ... 省略// 關鍵點部分 1 body = (genericConverter != null ? genericConverter.read(targetType, contextClass, msgToUse) :((HttpMessageConverter<T>) converter).read(targtestlass, msgToUse));// ... 省略 }后邊調(diào)用的就是 ?BeanPropertyMap 的find 方法。
? ? 再看一下 com.alibaba.fastjson。
?? ?通過修改 默認 json解析器。原來 AbstractJackson2HttpMessageConverter ?改為 ?FastJsonHttpMessageConverter
?? ?com.alibaba.fastjson.parser.deserializer.JavaBeanDeserializer
?? ?的 deserialze 方法。
?? ?可以看到 fastjson 將原來的屬性 放到 fieldinfo 中。后續(xù)操作的的都是fieldinfo 對象。
??
5. 測試
前面寫的還不夠清晰,我們可以寫個簡單的test方法自己測一下。
ATest.java
package com.test.test.test;import lombok.Data;@Data public class ATest{String aTest;String age;}TestJson.java
package com.test.test;import com.alibaba.fastjson.JSONObject; import com.test.controller.test.ATest; import org.junit.Test;import java.util.HashMap;public class TestJson{@Testpublic void testJson() {HashMap<Object, Object> hashMap = new HashMap<>();hashMap.put("aTest","111");hashMap.put("age","111");ATest test = JSONObject.parseObject(JSONObject.toJSONString(hashMap), ATest.class);System.out.println("fastjson=================="+test);ATest o = (ATest) net.sf.json.JSONObject.toBean(net.sf.json.JSONObject.fromObject(hashMap), ATest.class);System.out.println("net.sf.json=================="+o);} }可以發(fā)現(xiàn),fastjson 反序列化話的對象是正常的。
net.sf.json 是不行的。
net.sf.json 使用的是 org.apache.commons.beanutils.PropertyUtilsBean
getPropertyDescriptors?
beanInfo.getPropertyDescriptors();
可以看到獲取到的 beanInfo 的 propertyName 是 ATest。
事實證明, lombok ?這波操作確實有點問題,起碼不兼容市面上大部分的json包。
總結:
最開始以為是mvc 無法封裝 的問題,后來發(fā)現(xiàn)跟lombok有關(首字母小寫、第二個字母大寫時的get/set方法生成方式)。
form表單提交沒問題,發(fā)現(xiàn)跟json有關(序列化/反序列化)。
再換了幾個常見的json包。
fastjson 沒問題,net.sf.json 和 jackson 都不行。
lombok 這波操作就是逆規(guī)范的,沒什么好說的。如果非要這種命名的話,建議重寫get/set 方法。
總結
以上是生活随笔為你收集整理的lombok 的bug?lombok 导致 springmvc 使用 @RequestBody注解 接收 json数据 对象参数绑定失败的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 网络7层架构
- 下一篇: ofstream 二进制 文本_C/C+