目录
一、问题描述
首先业务场景很简单,就是一个模糊搜索查询接口。因为业务需求的需要,就新增了一个查询字段id,也就是根据id来筛选出列表中需要的数据。因为很简单的需求,所以就很自信的在原来的接口加了个接收参数id,修改后的接口如下(相信一些基础比较好的同志,已经可以发现问题的所在,哈哈,博主是承认的自己的基础确实不够扎实):
@GetMapping(value = "/listAlarmInfo")
public Result<PageUtil<DceAlarmInfoListVo>> listAlarmInfo(@RequestParam(value = "id", required = false) long id,
@RequestParam(value = "mcuName", required = false) String mcuName,
@RequestParam(value = "equipKey", required = false) String equipKey,
@RequestParam(value = "alarmSource", required = false) Integer alarmSource,
@RequestParam(value = "alarmLevel", required = false) Integer alarmLevel,
@RequestParam(value = "alarmType", required = false) Integer alarmType,
@RequestParam(value = "alarmStatus", required = false) Integer alarmStatus,
@RequestParam(value = "startDate", required = false) String startDate,
@RequestParam(value = "endDate", required = false) String endDate,
@RequestParam(value = "keyWords", required = false) String keyWords,
@RequestParam(value = "pageNum", required = false, defaultValue = "1") Integer pageNum,
@RequestParam(value = "pageSize", required = false, defaultValue = "10") Integer pageSize) {
PageUtil<DceAlarmInfoListVo> pageUtil = new PageUtil<>(dynamicEnvironmentService.listAlarmInfo(id,mcuName, equipKey, alarmSource, alarmLevel, alarmType, alarmStatus, keyWords, startDate, endDate), pageNum, pageSize);
return new SuccessResult<>(pageUtil);
}
通过postman调用,传id参数也是没问题的,都是可以正常得到结果的。
但是,问题就出在,这个id并不是必传的。当我们只是查询列表数据的时候, 也就是不传id的时候问题就来了。
二、解决过程
异常报错信息翻译过来的大概意思就是:存在一个长整型的的参数,由于被申明为基本类型,因此不能转换成空值。也就是我们新加的字段id定义为了long型,它接受不了空值。所以,知道原因了,拿解决办法也就很简单了,把long类型换成包装类型Long就可以了。
@GetMapping(value = "/listAlarmInfo")
public Result<PageUtil<DceAlarmInfoListVo>> listAlarmInfo(@RequestParam(value = "id", required = false) Long id,
@RequestParam(value = "mcuName", required = false) String mcuName,
@RequestParam(value = "equipKey", required = false) String equipKey,
@RequestParam(value = "alarmSource", required = false) Integer alarmSource,
@RequestParam(value = "alarmLevel", required = false) Integer alarmLevel,
@RequestParam(value = "alarmType", required = false) Integer alarmType,
@RequestParam(value = "alarmStatus", required = false) Integer alarmStatus,
@RequestParam(value = "startDate", required = false) String startDate,
@RequestParam(value = "endDate", required = false) String endDate,
@RequestParam(value = "keyWords", required = false) String keyWords,
@RequestParam(value = "pageNum", required = false, defaultValue = "1") Integer pageNum,
@RequestParam(value = "pageSize", required = false, defaultValue = "10") Integer pageSize) {
PageUtil<DceAlarmInfoListVo> pageUtil = new PageUtil<>(dynamicEnvironmentService.listAlarmInfo(id,mcuName, equipKey, alarmSource, alarmLevel, alarmType, alarmStatus, keyWords, startDate, endDate), pageNum, pageSize);
return new SuccessResult<>(pageUtil);
}
再次使用postMan测试,结果如下:
竟然有空指针异常???
打个断点看一下吧。由于接口层代码,并没有什么逻辑处理,都是直接调用的业务层代码,所以就直接再业务层的第一行代码打了个断点,再次用postman测试。what?没到断点,就直接报空指针异常了。
还是空指针异常!!
那这会是什么地方导致的空指针异常呢?
突然灵光闪现,我的业务层方法,这里接收的参数id还是使用的基本数据类型long。
虽然说,基本数据类型和它的包装类存在自动装箱和拆箱的机制。但是,如果在自动拆箱的时候包装类为空的话, 那么就会报空指针异常。我们可以看Long类型自动拆箱的源码如下:
/**
* Returns the value of this {@code Long} as a
* {@code long} value.
*/
public long longValue() {
return value;
}
通过源码,可以得知:当我们在使用Long的自动拆箱的时候,返回的就是包装类Long的属性value。而我们知道当对象是空的时候,我们如果访问空对象的属性也就会报空指针异常。
至此,我们知道原因所在之后,便可以把所有使用id字段的参数都改成使用包装类Long,便可。此时,在去使用postman测试,便不在报错。
三、总结
在我们的方法中有使用数据类型的参数的时候,最好都使用它的包装类,以免出现空指针等异常!