前言
有这么一个业务场景:部门 A 服务要应用部门 B 服务的业务数据,部门 A 服务应用部门 B 服务的业务数据前置条件是 B 部门必须要给 A 受权。B 部门的受权和业务数据分属为不同服务。其申请流程如下
因为 A 的鉴权信息的申请值是固定的,因而鉴权后果大概率也是固定值。过后 B 部门的业务服务开发共事,为了提高效率。就加了缓存,即 B 的业务服务会将 A 的鉴权后果缓存起来。过后写法形如下
private final LoadingCache<String,Boolean> checkSvcCache = Caffeine
.newBuilder().maximumSize(Constants.MAX_SIZE)
.expireAfterWrite(Conastants.EXPIRE, TimeUnit.DAYS)
.build(key -> loadCache(key));
@Nullable
private Boolean loadCache(@NonNull String key) {if(key.contains(Constant.UNDER_LINE)){
try {String[] arr = key.split(Constant.UNDER_LINE);
Integer ak = Integer.parseInt(arr[0]);
String sk = arr[1];
RPCResult<Boolean> result = authService.checkSvc(ak, sk);
if(result.getSuccess()){Boolean data = result.getData();
return data;
}
return false;
} catch (Exception e) {log.error("{}",e);
}
}
return false;
}
思考
大家看下上述代码块的写法有没有问题?
粗看貌似没啥问题,但理论是有点小问题的。当进行近程调用时,如果出现异常,此时布尔值会返回 false。这样就可能把正确的后果给覆盖了,比方明明都按约定的 ak,sk 传值了,后果返回鉴权失败。
修复
那要如何修复?扯一点哲学货色,这个世界不是非黑即白,其实可能还存在灰色地带。布尔值在 java 的世界中,也不是就只有 true 或者 false,当布尔值为包装类时,他还有一种状态是 null。因而能够批改为
@Nullable
private Boolean loadCache(@NonNull String key) {if(key.contains(Constant.UNDER_LINE)){
try {String[] arr = key.split(Constant.UNDER_LINE);
Integer ak = Integer.parseInt(arr[0]);
String sk = arr[1];
RPCResult<Boolean> result = authService.checkSvc(ak, sk);
if(result.getSuccess()){Boolean data = result.getData();
return data;
}
return false;
} catch (Exception e) {log.error("{}",e);
}
}
return null;
}
但这样改就没问题了吗,其实还是有问题,因为 null 值也不是正确后果。但咱们能够利用 null 来额定做一些异样兜底。比方呈现 null 时,就是有问题了,咱们能够对 A 进行敌对的提醒,而非返回鉴权失败,也便于提前裸露问题,而下次申请进来时,缓存会因为值为 null,再次触发近程调用
总结
异样流程思考很重要。。。