某天,运营反馈,某商品下单异常

1.原来是一个空指针报错

根据用户输入的下单关键信息搜索日志系统看到如下报错

stackTrace: "java.lang.NullPointerException
at com.auto.order.service.utils.OrderingUtils.buildParentOrderData(OrderingUtils.java:194)
at com.auto.order.service.cart.impl.OrderingCommonServiceImpl.handleStat(OrderingCommonServiceImpl.java:1221)
at com.auto.order.service.cart.impl.OrderingIndexServiceImpl.receive(OrderingIndexServiceImpl.java:1027)
at com.auto.order.service.impl.OrderApiServiceImpl.receive(OrderApiServiceImpl.java:1979)
at com.auto.order.site.controller.neworder.OrderingIndexController.receive(OrderingIndexController.java:368)

原来是个空指针错误,来看下194行代码是啥

1 parentOrderData.setRefCookie(orderingReceiveParamBo.getRefCookie());
2 parentOrderData.setCityId(orderingReceiveParamBo.getRuleCityId().intValue());//194行
3 parentOrderData.setSessionId(orderingReceiveParamBo.getSessionId() != null ? orderingReceiveParamBo.getSessionId() : "");

上面代码块第二行就是原文件里194行,判断得出应该是ruleCityId字段为空导致了空指针异常;又看了下parentOrderData对象和orderingReceiveParamBo对象的ruleCityId字段都是Integer类型,这里没有必要intValue,改之如下

2 parentOrderData.setCityId(orderingReceiveParamBo.getRuleCityId());//194行

上线后,以为问题就解决了呢,谁知依旧报错,继续翻看日志,发现如下报错

--- Cause: com.mysql.jdbc.exceptions.jdbc4.MySQLIntegrityConstraintViolationException: Column 'city_id' cannot be null
at org.springframework.jdbc.support.SQLStateSQLExceptionTranslator.doTranslate(SQLStateSQLExceptionTranslator.java:102)
at org.springframework.jdbc.support.AbstractFallbackSQLExceptionTranslator.translate(AbstractFallbackSQLExceptionTranslator.java:73)
at org.springframework.jdbc.support.AbstractFallbackSQLExceptionTranslator.translate(AbstractFallbackSQLExceptionTranslator.java:82)
at org.springframework.jdbc.support.AbstractFallbackSQLExceptionTranslator.translate(AbstractFallbackSQLExceptionTranslator.java:82)

2.看来不仅仅是一个空指针

数据库里设置了city_id字段是非空的,但是程序没有获取到city_id,为啥获取不到呢,继续排查city_id是怎么获取的

/**
* 获取所在城市
*/
public static int mallCityId(HttpServletRequest request){
try {
String ck = getCookieValue(request.getCookies(), "cookieCityId");
if ( "999999".equals(ck)) {
return 110100;
}
if (StringUtils.isNotBlank(ck) && Integer.parseInt(ck) > 0) {
return ck.indexOf("9999") > 0 ? Integer.parseInt(ck.substring(0, 2) + "0100") : Integer.parseInt(ck.substring(0, 4) + "00");
}
ck = getCookieValue(request.getCookies(),"area");
if ("999999".equals(ck)) {
return 110100;
}
if (StringUtils.isNotBlank(ck) && Integer.parseInt(ck) > 0) {
return ck.indexOf("9999") > 0 ? Integer.parseInt(ck.substring(0, 2) + "0100") : Integer.parseInt(ck.substring(0, 4) + "00");
}
} catch (Exception e) {
indexLog.error("mallCityId is error!",e);
}
return 110100;
}

  

代码中city_id是从cookie中获取的,但是这一段代码返回结果不可能为null,即使有异常,也该返回默认城市110100!继续看哪里调用了这个方法,原来是在拦截器方法里调用了这个方法取各种cookie,并做容错处理,主要代码如下

/**
* 方法执行前的拦截方法
*/
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
String sessionId = "";
Long pvId = 0L;
Long positionId = 0L;
Integer cityId = 0;
String sessionVid = "";
String refCookie = "";
String sessionIp=""; Long s = System.currentTimeMillis();
try {
sessionId = getCookieValue(request.getCookies(),"sessionid");
sessionVid = getCookieValue(request.getCookies(),"sessionvid");
sessionIp = getCookieValue(request.getCookies(),"sessionip");
pvId = Long.valueOf(StringUtils.isNotBlank(getCookieValue(request.getCookies(), "mpvareaid")) ? getCookieValue(request.getCookies(), "mpvareaid") : "0");
positionId = Long.valueOf(StringUtils.isNotBlank(getCookieValue(request.getCookies(), "autohomeareaid")) ? getCookieValue(request.getCookies(), "autohomeareaid") : "0");
cityId = mallCityId(request);
request.setAttribute(CUR_SESSION_ID,sessionId);
request.setAttribute(CUR_SESSION_IP,sessionIp);
request.setAttribute(CUR_SESSION_VID,(sessionVid == null?"":sessionVid));
request.setAttribute(CUR_REF_COOKIE,(refCookie == null?"":refCookie));
request.setAttribute(CUR_PV_ID,pvId);
request.setAttribute(CUR_POSITION_ID,positionId);
request.setAttribute(CUR_CITY_ID,cityId);
request.setAttribute(PARTNER, getCookieValue(request.getCookies(), PARTNER));
request.setAttribute(CURR_UNIX_TIME, System.currentTimeMillis());
} catch (Exception e) {
log.error("get interceptor error:", e);
}
timeLog.info("interceptor end timecost=======>"+(System.currentTimeMillis()-s));
return true;
}

  这个拦截器方法,粗看下去没有发现任何问题,如果这个方法有异常,但是日志系统死活没有看到catch打印的error堆栈信息;如果没异常,按流程走下来,cityId字段不可能为空啊!怎么办,笨方法,加日志,我把这个方法调用 mallCityId 方法之上每隔一行都加了日志,看哪行有猫腻

  通过加日志定位到了问题所在,上面代码块的第18行一直走不到,18行就是这个

pvId = Long.valueOf(StringUtils.isNotBlank(getCookieValue(request.getCookies(), "mpvareaid")) ? getCookieValue(request.getCookies(), "mpvareaid") : "0");

  仔细看这一行,真有可能出了问题,如果从cookie里取出来的不是数字,还要 Long.valueOf 肯定就报错了,But为啥捕获不到异常,再看catch块log打印到哪里了

    private static Logger log = LoggerFactory.getLogger(CommonInterceptor.class);
private static final Logger timeLog = LoggerFactory.getLogger("creat-order-time");
private static final Logger indexLog = LoggerFactory.getLogger("access-index");

  log对应的是 CommonInterceptor.class ,但是log4j2.xml文件里并没有配置这个类文件,其他两个日志文件在log4j2.xml文件里都有配置,唯独这个CommonInterceptor.class 没有映射,那日志打印到哪里了呢?最后在tomcat的catalina.out文件看到了报错

  上图报错行,正好对应的就是拦截器里第18行,从cookie里取出来的mpvareaid是undefined,所以类型转换就报错了,但是由于缺少log4j日志配置,没有在常规业务日志路径捕获到该异常。最后把业务日志路径改了,兼容了undefined情况,问题最终解决

3.总结两点

  第一:未兼容从cookie里取出来的异常数据undefined

  第二:日志打印不规范,没有合理配置日志路径

最新文章

  1. DDD 领域驱动设计-两个实体的碰撞火花
  2. linux 之静默安装oracle
  3. UICollectionView移动
  4. [GRYZ2014]最大连续子序列的和
  5. 运用linq查找所有重复的元素
  6. [SQL注入2]FROM SQL INJECTION TO SHELL: POSTGRESQL EDITION
  7. jquery+html三级联动下拉框
  8. 浏览器缓存机制<转>
  9. Mac下截屏方法
  10. Android24以上拍照代码
  11. trinitycore 魔兽服务器源码分析(一) 网络
  12. Python 索引迭代
  13. dplyr-高效的数据变换与整理工具--转载
  14. ajax在jQuery中的应用 (1)加载异步数据
  15. scala中的一些特殊符号的意义
  16. J2SE 8的脚本
  17. 上云、微服务化和DevOps,少走弯路的办法
  18. response.sendRedirect()和request.getRequestDispatcher().forward(request,response)的区别
  19. JavaScript中的arguments详解
  20. Vue学习笔记之Vue的使用

热门文章

  1. lua脚本分解字符串
  2. HTML创建文本框的3种方式
  3. luoguP1514 引水入城 题解(NOIP2010)(Bfs+贪心)
  4. ubantu18.04中mysql8.0设置远程连接的问题
  5. 53.Coin Change(找硬币)
  6. PHP导出带有emoji表情的文本到excel文件出问题了
  7. Python的基本类型(list,tuple)
  8. linux c 链接详解4-共享库
  9. Java运行显示无待入值
  10. linux-java