1200字范文,内容丰富有趣,写作的好帮手!
1200字范文 > lombok 的bug?lombok 导致 springmvc 使用 @RequestBody注解 接收 json数据 对象参数绑定失败

lombok 的bug?lombok 导致 springmvc 使用 @RequestBody注解 接收 json数据 对象参数绑定失败

时间:2019-04-16 14:41:20

相关推荐

lombok 的bug?lombok 导致 springmvc 使用 @RequestBody注解 接收 json数据 对象参数绑定失败

大家好,我是烤鸭:

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,而作者也提出了解决办法。

/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));// ... 省略}

后边调用的就是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;@Datapublic 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);}}

可以发现,fastjson 反序列化话的对象是正常的。

net.sf.json 是不行的。

net.sf.json 使用的是mons.beanutils.PropertyUtilsBean

getPropertyDescriptors

beanInfo.getPropertyDescriptors();

可以看到获取到的 beanInfo 的 propertyName 是 ATest。

事实证明, lombok 这波操作确实有点问题,起码不兼容市面上大部分的json包。

总结:

最开始以为是mvc 无法封装 的问题,后来发现跟lombok有关(首字母小写、第二个字母大写时的get/set方法生成方式)

form表单提交没问题,发现跟json有关(序列化/反序列化)

再换了几个常见的json包。

fastjson 没问题,net.sf.json 和 jackson 都不行

lombok 这波操作就是逆规范的,没什么好说的。如果非要这种命名的话,建议重写get/set 方法。

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。