SLF4J: Failed toString() invocation on an object of type [java.util.HashMap] 的解决

SLF4J: Failed toString() invocation on an object of type [java.util.HashMap] 的解决

  1. 问题背景:

对体类Bean进行 BeanUtils.describe(purchaseCatalogBo);转换成Map,但是日志打印报错,并且从map里获取参数报错,报错明细如下:

SLF4J: Failed toString() invocation on an object of type [java.util.HashMap]
Reported exception:
java.lang.StackOverflowError
        at java.lang.String.valueOf(String.java:2994)
        at java.lang.StringBuilder.append(StringBuilder.java:131)
        at java.util.AbstractMap.toString(AbstractMap.java:534)
        at java.lang.String.valueOf(String.java:2994)
        at java.lang.StringBuilder.append(StringBuilder.java:131)
        at java.util.AbstractMap.toString(AbstractMap.java:536)
        at java.lang.String.valueOf(String.java:2994)
        at java.lang.StringBuilder.append(StringBuilder.java:131)
        at java.util.AbstractCollection.toString(AbstractCollection.java:462)
        at java.lang.String.valueOf(String.java:2994)
        at java.lang.StringBuilder.append(StringBuilder.java:131)
        at java.util.AbstractMap.toString(AbstractMap.java:536)
        at java.lang.String.valueOf(String.java:2994)
        at java.lang.StringBuilder.append(StringBuilder.java:131)
        at java.util.AbstractMap.toString(AbstractMap.java:536)
        at java.lang.String.valueOf(String.java:2994)
        at java.lang.StringBuilder.append(StringBuilder.java:131)
        at java.util.AbstractCollection.toString(AbstractCollection.java:462)
        at java.lang.String.valueOf(String.java:2994)
        at java.lang.StringBuilder.append(StringBuilder.java:131)
        at java.util.AbstractMap.toString(AbstractMap.java:536)
        at java.lang.String.valueOf(String.java:2994)
        at java.lang.StringBuilder.append(StringBuilder.java:131)

并且更奇怪的是在本机验证是没有问题的,只有在线上环境才会出现,很是令人头疼,心想肯定是哪里的底层没有涉及到导致这个表面的错误浮现。

  1. 解决方案:
    使用阿里巴巴的json转换。
 将 Map reqMap = BeanUtils.describe(allChannelsCheckResReq);  改成
 Map reqMap = JSON.parseObject(JSON.toJSONString(allChannelsCheckResReq), Map.class);
  1. 问题原因

经过网上查证,问题原因很可能是 实体类使用JPA方法来实现实体类之间的对应关系和BeanUtils.describe()方法的tostring方法都无休止地相互调用引起的。因为BeanUtils.describe()的原理是 BeanUtils调用 BeanUtilsBean的这个getNestedProperty方法,该方法在读取值之后,会再调用一次(getConvertUtils().convert(value));,进行类型转化成String。即转化出来的Map的value都是String。

  1. 总结:
    BeanUtils虽然做了封装提高了开发效率,但是阿里巴巴的json感觉更优秀点。以后转换多多使用json
  2. 拓展:

BeanUtils.describe与PropertyUtils.describe区别
BeanUtils.describe转换出来的值为string; PropertyUtils.describe 转换出来的值不做转换,但是两者都会将class也转换到Map里,如图所示

PurchaseCatalogBo purchaseCatalogBo=new PurchaseCatalogBo();
        purchaseCatalogBo.setRsId("123");
        purchaseCatalogBo.setPricePre(88);
        purchaseCatalogBo.setUpdatime(new Date());
        Map describe = BeanUtils.describe(purchaseCatalogBo);
        System.out.println(JSON.toJSONString(describe));
        Map describe1 = PropertyUtils.describe(purchaseCatalogBo);
        System.out.println(JSON.toJSONString(describe1));
        Map map = JSON.parseObject(JSON.toJSONString(purchaseCatalogBo), Map.class);
        System.out.println(JSON.toJSONString(map));

输出结果:
BeanUtils.describe{“pricePre”:“88”,“rsId”:“123”,“updatime”:“Mon Feb 03 20:19:18 CST 2020”,“class”:“class com.chinaunicom.cbss2.rc.external.bean.PurchaseCatalogBo”}

PropertyUtils.describe{“pricePre”:88,“rsId”:“123”,“updatime”:1580732358529,“class”:“com.chinaunicom.cbss2.rc.external.bean.PurchaseCatalogBo”}

Json
{“updatime”:1580732358529,“pricePre”:88,“rsId”:“123”}

你可能感兴趣的:(后端问题,java,spring)