记录一次排查问题遇到apache.commons.beanutils包的坑

本文介绍了在使用Apache Commons Beanutils时遇到的一个bug,即自定义的日期转换器未生效,导致String转Date时出错。通过分析源码,发现由于线程上下文类加载器和弱引用HashMap的使用,导致多线程环境下转换器被错误清理。解决方案是在每次转换前重新注册个性化日期转换器。
摘要由CSDN通过智能技术生成

引言 

        在开发过程中,难免需要用到对象转换器,比如apache的BeanUtils、ConvertUtils还有spring的BeanUtils。我们在公司的项目中就使用了apache的BeanUtils和ConvertUtils作为公共的对象转换工具。但是在没有充分理解源代码的情况下,添加个性化Converter就会出现意想不到的bug。下面我来介绍一下我在排查问题中遇到的这个bug。

问题

        本文采用的是jdk1.8 commons-beanutils 1.9.3的代码。先来描述一下我遇到的问题,我的使用场景是将String类型的日期转换成Date类型的日期,当然我事先已经配置好了String类型转换Date类型的转换器。但是还是出现了如下报错。而且这个报错非常有特点:

  1. 出现一次以后就会一直出现,重启后又恢复
  2. 同样的代码在某一个线程会报错,在其他线程又不报错非常奇怪。
2019-12-03 09:02:27.119 [TID:136.209.15753349468560005] [http-nio-9092-exec-59] WARN  org.apache.commons.beanutils.converters.DateConverter -    DateConverter does not support default String to 'Date' conversion.
2019-12-03 09:02:27.119 [TID:136.209.15753349468560005] [http-nio-9092-exec-59] WARN  org.apache.commons.beanutils.converters.DateConverter -    (N.B. Re-configure Converter or use alternative implementation)
org.apache.commons.beanutils.ConversionException: DateConverter does not support default String to 'Date' conversion.
	at org.apache.commons.beanutils.converters.DateTimeConverter.toDate(DateTimeConverter.java:474)
	at org.apache.commons.beanutils.converters.DateTimeConverter.convertToType(DateTimeConverter.java:347)
	at org.apache.commons.beanutils.converters.AbstractConverter.convert(AbstractConverter.java:169)
	at org.apache.commons.beanutils.converters.ConverterFacade.convert(ConverterFacade.java:61)
	at org.apache.commons.beanutils.ConvertUtilsBean.convert(ConvertUtilsBean.java:566)
	at org.apache.commons.beanutils.ConvertUtils.convert(ConvertUtils.java:282)

       其次,我们在代码中是自定义了BeanUtils,只是使用了ConvertUtils,当然大部分的BeanUtils代码还是和apache的BeanUtils代码一致的。以下是这个问题代码。

public class RabbitBeanUtils {
    static {
        ConvertUtils.register(new ConverterWrapper(ConvertUtils.lookup(Date.class)) {
            @Override
            public Object convert(Class type, Object arg) {
                if (arg instanceof Date) {
                    return arg;
                }
                if (arg instanceof Number) {
                    Number value = (Number) arg;
                    return new Date(value.longValue());
                } else if (arg instanceof String) {
                    return TypeConverter.parse((String) arg);
                }
                return super.convert(type, arg);
            }
        }, Date.class);

        ConvertUtils.register(new ConverterWrapper(ConvertUtils.lookup(List.class)) {
            @Override
            public Object convert(Class type, Obj
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值