记一次帮同事排查使用easypoi的问题

1.问题背景

一个同事,在做一个导出excel的时候,后台报空指针异常,自己看了好一会代码,发现自己写的代码也没有什么问题,一时找不到问题所在,让我帮忙检查一下。毕竟多个人多双眼睛嘛。哈哈!

由于公司用的easypoi,所以在做导出的时候,就比较方便,代码也就那么几行。我同事是这么写的。

//这个是调用indexScoreMonitoringService的一个方法返回DTO,这个DTO就是封装了需要导出excel的数据
List scoreCollinearityParentClassDTOS = indexScoreMonitoringService.scoreCollinearity(ratingModelReportQuery, indexScoreIdsList, 1);
//调用公司统一封装的EasyPoiUtil工具类下载excel文件
EasyPoiUtil.exportExcel(scoreCollinearityParentClassDTOS, null, EasyPoiUtil.CHART_NAME[cid], ScoreCollinearityExcelDTO.class, EasyPoiUtil.CHART_NAME[cid] + ".xls", response);

下面贴一下该工具类中exportExcel方法的相关描述

/**
 * 功能描述:复杂导出Excel,包括文件名以及表名,不创建表头
 *
 * @author yan
 * @date  2019/8/5 14:11
 * @param list 导出的实体类
 * @param title 表头名称
 * @param sheetName sheet表名
 * @param pojoClass 映射的实体类
 * @param fileName
 * @param response
 * @return
 */

下面在贴一下ScoreCollinearityParentClassDTO的相关代码

private static final long serialVersionUID = 4575184647737532340L;
@Excel(name = "共线性", width = 40 ,orderNum="4")
public   String collinearity;
//......省略下面其他生成set与get的代码
//......

另外我同事说,他在构造DTO的时候其实是用的ScoreCollinearityParentClassDTO的一个子类ScoreCollinearityExcelDTO,所以我把ScoreCollinearityExcelDTO也贴一下。具体封装DTO就不贴了。下面是有关ScoreCollinearityExcelDTO的相关代码

@Excel(name = "日期", width = 40)
private  String month;
@Excel(name = "模型名称", width = 40)
private  String modelName;
@Excel(name = "模块名A~指标名A --- 模块名B~指标名B", width = 40)
private  String ModuleNameIndexName;
//......省略下面其他生成set与get的代码
//......

这里再记录一点,同事事先排查问题的时候,发现导出只有父类的一列值,所以他本地修改了代码,用返回子类集合,然后报空指针异常。所以为了与他本地代码保持一致,我现在我本地修改一下代码。具体修改后的代码我就不贴出来了。就是修改封装DTO的Service返回子类集合,然后用子类集合进行接受。

2.解决问题

上面进行了问题的相关描述。由于代码不多,我先通过肉眼检查一下代码什么地方不对。最后发现ScoreCollinearityExcelDTO中的一个属性定义很不符合规范

首字母写成了大写。也许是同事在什么地方拷贝过来的,忘记修改了。我先将这个地方改成小写。然后自测一下,发现问题得到了解决。哈哈。感觉好顺利哦。于是我让同事把这个地方改了,提交代码,先把问题解决,不要卡在这儿。

3.跟踪源码,分析原因

问题是解决了。但是为什么呢?我们不能胡乱一懵,将问题解决,就不管了啊。就算当时上班比较忙,也要备注下。事后也要对问题进行分析,找出问题根本问题所在。知道为什么。所以开始我我查看easypoi源码的历程。

我现在我本地将代码还原。然后调试将异常信息打印出来。发现也不是空指针问题啊,尴尬了。 记一次帮同事排查使用easypoi的问题_第1张图片
而且报错也很也很详细,将字段名都描述出来了。难不成我这边跟他那边不一样。 记一次帮同事排查使用easypoi的问题_第2张图片
记一次帮同事排查使用easypoi的问题_第3张图片
很明显,这个获取method没有获取到,为null了。我们这这里打一个断点,进行调试。发现的确为null 记一次帮同事排查使用easypoi的问题_第4张图片
查看getMethods 记一次帮同事排查使用easypoi的问题_第5张图片
返回的是一个map,key为moduleNameIndexName,但传入的是ModuleNameIndexName,当然找不到咯。那么下面我们来看看,这个getMethods是怎么封装的。下面是我一直往上找的相关源码,重点我都标记出来了。
记一次帮同事排查使用easypoi的问题_第6张图片
记一次帮同事排查使用easypoi的问题_第7张图片
记一次帮同事排查使用easypoi的问题_第8张图片
easypoi底层是通过过去所有的get方法进行封装到Map集合的,key为去掉方法名,去掉get后将首字母小写作为key。所以 getModuleNameIndexName ----> moduleNameIndexName
而获取的时候是通过属性名获取的,这里不管是moduleNameIndexName或ModuleNameIndexName,生成后的get方法相同。所以导致了不对应的问题。

4.小结

这里仅仅是由于同事大意才导致的问题,所以以后写代码的时候,能复制就尽量复制吧,什么属性名,变量名,复制粘贴最好,自己手敲很容易出错。另外,easypoi是严格按照类编写规范来解析的,获取方法的时候,通过获取打了@Excel注解的字段进行查找,可惜的是在封装方法集合时又是通过get方法进行截取封装map。若是easypoi都通过字段进行获取,那么就不存在这个问题了。但是我们怎么能怪人家工具呢,现在字段名首字母小写都是业界公认的编码规范。为了避免不必要的问题,所以还是必须要遵守的。

转载于:https://my.oschina.net/u/3553496/blog/3100690

你可能感兴趣的:(记一次帮同事排查使用easypoi的问题)