记一次奇葩的问题排查经历(fastjson Tomcat)
问题背景
这个问题奇葩之处在于IDE中没问题,发到Tomcat容器中报错。在测试类中没问题,嵌入业务流程报错。解决问题简单,但是排查问题花了很长时间,一直搞到晚上9点。站长觉得有必要梳理下这个过程,特此发到博客网站,以供大家参考。异常信息:
[com.dbsoft.whjd.action.DetectionCommisionSheetAction]java.lang.ClassCastException: java.lang.String cannot be cast to com.alibaba.fastjson.JSONArray
网上对这个问题的解决方案也是一大堆,但是尝试之后并不理想。
站长从以下几个方面进行了排查:
代码问题(Debug一步步跟进,定位报错行)
测试类(抽取出有关代码,放到测试类中执行,正常)
业务流中(即原始代码,eclipse中正常运行,但是打成war包发到Tomcat报错)
数据库问题(是否是不同测试数据造成的)
本地库(放弃)
远程库(连接同一数据库,测试同一条数据,同样报错,数据本身没问题)
Tomcat容器问题(测试不同版本)
本地(Tomcat8.0,同样报错)
远程(Tomcat8.5,同样报错)
依赖工具包问题(检查是否有jar包冲突、版本过低问题)
fastjson(放弃,全部采用hutool工具解析json)
hutool(使用:4.1.3,最新:5.3.6,hutool推荐使用的JDK是1.8)
JDK版本(检查是否是JDK版本问题,机动车项目使用的版本较低,若更换JDK风险巨大,最后排查)
1.6(实际使用版本,上产环境如此,历史遗留问题)
1.8(开发测试版本)
其他问题
代码风格不统一:一个类很多人修改,光JSON解析工具就引入了三种。
代码修改后未生效:clean/update
尝试方法:
1)拿到接口返回json数据后,根据网上常见解决方案,仔细检查格式是否正确。(检查格式无误,排除数据问题)
2)解压war包,检查是否缺失jar包,比如hutool包,fastjson包等。(检查不缺失,排除引入问题)
3)反编译class,检查代码是否和eclipse中一致。(检查一致,排除打包问题)
4)测试是否是Tomcat问题,把war包发给同事,在其Tomcat中测试。(检查同样有问题,排除Tomcat问题)
5)抽取问题代码到单独的测试类,用的解析工具为hutool4.1.3版本。(测试没问题,此时用的JDK是1.8)
6)将原始代码换成上面的测试类代码运行,同时注释掉fastjson相关的引入。(报一个JDK内部的异常,无详细说明,怀疑是版本不兼容)
7)去hutool官网查看最新版本,引入替换掉项目中的老版本。(问题解决)
附代码:
// 根据车牌号和颜色判断是否在遥感黑名单 String getDetectRepair = "http://60.xxx.58.xx:8x/api/DetectDataApi/GetDetectRepair"; // M站竣工出厂合格证(根据车牌号和颜色) String getCertificate = "http://60.xxx.58.xx:8x/api/DetectDataApi/GetCertificate"; //同事原来代码 com.alibaba.fastjson.JSONObject jsonObjectBlack = new com.alibaba.fastjson.JSONObject(); jsonObjectBlack.put("plateNum", detectionCommisionSheetPage.getLicence()); jsonObjectBlack.put("plateColor", detectionCommisionSheetPage.getLicenseColor().trim().substring(0, 1)); //修改后代码 Map param2 = new HashMap<Object, Object>(); param2.put("plateNum", detectionCommisionSheetPage.getLicence()); param2.put("plateColor", detectionCommisionSheetPage.getLicenseColor().trim().substring(0, 1)); //hutool工具类 String getDetectRepairResponse = HttpUtil.post(getDetectRepair,param2); String getCertificateResponse = HttpUtil.post(getCertificate,param2);
单独测试类
//单独测试类 Map param = new HashMap<>(); param.put("plateNum", "皖B01958"); param.put("plateColor", "蓝"); //hutool工具类 String result = HttpUtil.post(getDetectRepair,param); String result2 = HttpUtil.post(getCertificate,param); JSONObject resultObj = JSONUtil.parseObj(result2); JSONObject data = resultObj.getJSONArray("Data").getJSONObject(0); System.out.println(data);