【快递时效明细接口不通】BUG修复
昨晚上线了一个新功能,快递时效明细获取快递的预计到达时间。
这个接口,我之前已经写好了,原本传参中需要fromCity(出发地城市)和toCity(目的地城市),这两个字段原本是让采购录入的,后来由于某种原因,需要程序自动获取。
toCity其实对应的就是供应商的地址,这个字段在SAP中有维护,这个好解决。
fromCity怎么获取呢?
在推送报文是有resultv2这个字段
如果设置为6,那么推送的报文中,将会增加出发城市的名称。
因此需要将推送来的报文中,获取这个name的值。
我的逻辑是,如果预计到达时间为空,并且toCity不为空,那么就去获取fromCity,如果fromCity不为null,再去获取预计到达时间,
if (StringUtils.isEmpty(express.getArriveTime()) && StringUtils.isNotEmpty(express.getToCity())) {
//arriveTime为null,说明还没有调用接口获取预计到达时间
String fromCity = getFromCity(param);
if(StringUtils.isNotEmpty(fromCity)){
Map<String, String> paramMap = new HashMap<>();
paramMap.put("secret_key", secretKey);
paramMap.put("secret_code", secretCode);
// secretSign = SignUtils.sign(key+secretSecret)
paramMap.put("secret_sign", secretSign);
paramMap.put("from", fromCity);
paramMap.put("to", express.getToCity());
paramMap.put("companyList", express.getCompanyCode());
paramMap.put("orderTime", dataList.get(dataList.size()-1).getFtime());
String sendText = new Gson().toJson(paramMap);
String response = getExpressVo(paramMap);
express.setFromCity(fromCity);
handleResponseAndSaveArriveTime(sendText, response, express);
}
}
快递100的报文是通过Gson来解析的,那我也通过Gson来解析。
// 从回传报文中获取出发城市
private String getFromCity(String param) {
try {
JsonObject jsonObject = JsonParser.parseString(param).getAsJsonObject().getAsJsonObject("lastResult").getAsJsonObject("routeInfo").getAsJsonObject("from");
String fromCity = jsonObject.get("name").getAsString();
return fromCity.replace(",","");
} catch (JsonParseException e) {
return null;
}
}
第一个BUG:NullPointerException
之所以这样写,是因为要兼容之前的业务逻辑,之前的订阅服务传的resultv2=1,没有routeInfo,
如果不加try,catch会直接NullPointerException,最终会交给全局异常处理类GlobalExceptionHandler来执行。
全局异常处理类 GlobalExceptionHandler
/**
* 全局异常处理器
*/
@RestControllerAdvice
public class GlobalExceptionHandler{
/**
* 拦截未知的运行时异常
*/
@ExceptionHandler(RuntimeException.class)
public AjaxResult handleRuntimeException(RuntimeException e, HttpServletRequest request) {
String requestURI = request.getRequestURI();
log.error("请求地址'{}',发生未知异常.", requestURI, e);
return AjaxResult.error(e.getMessage());
}
}
尽管我的设想是正确的,通过异常捕获不上抛,而是返回null,跳过获取预计时间的逻辑。
但是当我把项目部署到生产环境的时候,异常信息一个接一个,依然报NullPointerException。
最终导致后续的业务全部回滚,所有的处理都失败。
我排查了很久,也查不出什么问题,无奈之下用postman模拟了一次请求,打上断点,发现果然报NullPointerException。
我大吃一惊,心想不会吧。
仔细看代码,顿时把我看笑了。
原来我写的catch (JsonParseException e)
,并没有捕获NullPointerException
。
于是把捕获的异常直接改为Exception,终于可以通过了。
第二个BUG:sub_time为空
服务跑到第二天早上我上班,一看,主表里的订阅记录,条条都是成功状态,但是sub_time(订阅时间)字段没有值。
我看下代码逻辑:
<update id="updateSysExpress" parameterType="SysExpress">
update sys_express
<trim prefix="SET" suffixOverrides=",">
<if test="expressNum != null and expressNum != ''">express_num = #{expressNum},</if>
<if test="companyCode != null and companyCode != ''">company_code = #{companyCode},</if>
<if test="status != null">status = #{status},</if>
<if test="subStatus != null">sub_status = #{subStatus},</if>
<if test="subParam != null">sub_param = #{subParam},</if>
<if test="subResult != null">sub_result = #{subResult},</if>
<if test="subResult != null">sub_result = #{subResult},</if>
<if test="arriveTime != null">arrive_time = #{arriveTime},</if>
<if test="subTime = null">sub_time = SYSDATE() + INTERVAL 8 hour,</if>
<if test="remark != null">remark = #{remark},</if>
</trim>
where express_id = #{expressId}
</update>
我去 <test=“subTime = null”>,竟然只有一个等号,要写也应该是subTime == null
算了,直接在入参的时候设置好subTime。
另外还遇到一个小BUG,就是主表中sub_time(订阅时间)字段
由此引发了好几个BUG。
NullPointerException