我要建设公司网站,子域名做微信开放平台网站应用,网站建设中模板代码,长沙模板建站哪家好大家好#xff0c;我是烤鸭#xff1a; lombok 导致 springmvc 使用 RequestBody注解 接收 json数据 对象参数绑定失败。 环境版本#xff1a; spring 5.x
1. 场景复现 问题出现在创建对象的属性名称。比如我有一个类中的属性值是 String aTest; 首字…大家好我是烤鸭 lombok 导致 springmvc 使用 RequestBody注解 接收 json数据 对象参数绑定失败。 环境版本 spring 5.x
1. 场景复现 问题出现在创建对象的属性名称。比如我有一个类中的属性值是 String aTest; 首字母小写第二个字母大写。 lombok 生成的get/set 方法是 getATest/setATest。 而依据java的规范(用各种ide生成的get/set方法) 应该是 getaTest/setaTest。
2. 问题猜测 lombok 生成的方法不符合 JavaBean get/set 规范导致mvc 无法封装进入对象。 尝试 form表单提交的方式 是没有问题的。 问题在于json 的方式。或者说在于json序列化和反序列化时。 spring json的包 默认使用的 com.fasterxml.jackson 可以看一下 com.fasterxml.jackson.databind.deser.impl.BeanPropertyMap 的 _findWithAlias 方法如图 BeanPropertyMap 获取到类中的属性是 atest而前台传入的key是 aTest无法匹配。 将 前台传参改为 {atest:1,age:2} 就可以匹配上了。
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) :((HttpMessageConverterT) converter).read(targtestlass, msgToUse));// ... 省略
} 后边调用的就是 BeanPropertyMap 的find 方法。 再看一下 com.alibaba.fastjson。 通过修改 默认 json解析器。原来 AbstractJackson2HttpMessageConverter 改为 FastJsonHttpMessageConverter com.alibaba.fastjson.parser.deserializer.JavaBeanDeserializer 的 deserialze 方法。 可以看到 fastjson 将原来的属性 放到 fieldinfo 中。后续操作的的都是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() {HashMapObject, Object hashMap new HashMap();hashMap.put(aTest,111);hashMap.put(age,111);ATest test JSONObject.parseObject(JSONObject.toJSONString(hashMap), ATest.class);System.out.println(fastjsontest);ATest o (ATest) net.sf.json.JSONObject.toBean(net.sf.json.JSONObject.fromObject(hashMap), ATest.class);System.out.println(net.sf.jsono);}
}
可以发现fastjson 反序列化话的对象是正常的。 net.sf.json 是不行的。 net.sf.json 使用的是 org.apache.commons.beanutils.PropertyUtilsBeangetPropertyDescriptors beanInfo.getPropertyDescriptors(); 可以看到获取到的 beanInfo 的 propertyName 是 ATest。 事实证明 lombok 这波操作确实有点问题起码不兼容市面上大部分的json包。 总结 最开始以为是mvc 无法封装 的问题后来发现跟lombok有关(首字母小写、第二个字母大写时的get/set方法生成方式)。 form表单提交没问题发现跟json有关(序列化/反序列化)。 再换了几个常见的json包。fastjson 没问题,net.sf.json 和 jackson 都不行。 lombok 这波操作就是逆规范的没什么好说的。如果非要这种命名的话建议重写get/set 方法。