那些年,我们写过的低级BUG,警钟长鸣

又一个低级的生产BUG

if(newDto.getStoreName().equals(oldDto.getStoreName()) &&
   newDto.getStoreCode().equals(oldDto.getStoreCode()) &&
   newDto.getGoodsName().equals(oldDto.getGoodsName()) &&
   newDto.getGoodsSpec().equals(oldDto.getGoodsSpec()) &&
   newDto.getStallName().equals(oldDto.getStallName()) &&
   newDto.getUnitName().equals(oldDto.getUnitName())){
   //不更新
}else{
    updList.add(newDto);
}
  • 问题是:没有对属性null做判断导致NPE
    修改后的代码:
if(Objects.equals(newDto.getStoreName(),oldDto.getStoreName()) &&
   Objects.equals(newDto.getStoreCode(),oldDto.getStoreCode()) &&
   Objects.equals(newDto.getGoodsName(),oldDto.getGoodsName()) &&
   Objects.equals(newDto.getGoodsSpec(),oldDto.getGoodsSpec()) &&
   Objects.equals(newDto.getStallName(),oldDto.getStallName()) &&
   Objects.equals(newDto.getUnitName(),oldDto.getUnitName())){
   //不更新
}else{
    updList.add(newDto);
}

java.util包都提供这个工具类了,还有什么不用起来的理由!!出这种问题太他妈丢人了,写的时候是咋想的啊!

又一个低级的生产BUG

public static MultiPriceInfo getMultiPriceInfo(List<MultiPriceInfo> multiPriceInfos, String code) {
        if(CollectionUtils.isEmpty(multiPriceInfos)){
            return null;
        }
        for(MultiPriceInfo priceInfo : multiPriceInfos){
            if(priceInfo.getPriceCode().equals(code)){
                return priceInfo;
            }
        }
        return null;
    }
  • 问题1 作为一个public方法,没有校验参数code
  • 问题2. priceInfo.getPriceCode().equals(code)可能会抛出NPE,因为priceInfo.getPriceCode()可能会返回null。

修改以后的代码:

public static MultiPriceInfo getMultiPriceInfo(List<MultiPriceInfo> multiPriceInfos, String code) {
		// 增加对code的校验
        if(CollectionUtils.isEmpty(multiPriceInfos) || StringUtils.isEmpty(code)){
            return null;
        }
        for(MultiPriceInfo priceInfo : multiPriceInfos){
        	// 前面已经确保了code不是null
            if(code.equals(priceInfo.getPriceCode())){
                return priceInfo;
            }
        }
        return null;
    }

两个修改点:

  • 增加对入参code为空的校验。
  • 改为code.equals(priceInfo.getPriceCode())。

就因为这个小小的问题,从凌晨0点搞到将近3点,就是找不到问题在哪,对代码还是有敬畏之心,不能太随意,安安稳稳躺床上睡觉它不香吗!!!

还有一点:如果是异步执行,一定要在异步方法的最外层加一个try-catch-finally进行兜底,否则全局异常拦截器拦截不到,再没有catch的话,就只能进shell看日志了!就怕没有shell的权限!

又一个低级的生产BUG

上周五,生产环境的二维码下载功能开始频繁报警,看了下代码,下载二维码这个功能服务端提供了2个接口,一个是生成二维码的压缩包,放到tomcat的临时目录里面,然后第二个是下载接口,现在的问题是,第一个接口没问题,第二个接口报的NPE。第二个接口非常简单,就是读取文件写到respoonse里面,如果NPE那就只有一个可能,那就是下载的文件不存在。并且这个接口有一定概率报错,还不是必现的,我只好猜测因为下载的文件是存放在临时目录,是不是因为系统硬盘空间不足而被系统删除了,但是本地怎么也模拟不出来!在这个方面浪费了大量的时间,还是没找到一点头绪,幸亏系统有全链路监控日志,后来仔细观察日志,才发现是异常是在一个Aop的拦截器里面抛出来,根本不是业务代码抛出来的!它是这么写的:

@Aspect
@Component
public class LogApiAdvice {
    @Around("@annotation(org.springframework.web.bind.annotation.RequestMapping)")
    public Object doAround(ProceedingJoinPoint joinPoint) throws Throwable {
        try {
            Object result = joinPoint.proceed();
            if (result.getClass().isAssignableFrom(ApiResult.class)) {
               ....
            } else {           
              ....    
            }
            return result;
        } catch (Throwable thr) {
            ....
            throw thr;
        }
    }
}

我们的下载的接口是这样的:

@ApiOperation("下载二维码")
@RequestMapping(value = "/downCodeZip")
public void downCodeZip(HttpServletResponse response, String zipFilePath) {
        
}

很显然,方法的返回值是null,因此在aop里面就发生了NPE!很低级的一个失误,导致生产不停报警,最终代码回滚,写代码还是得注意啊!

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值