来源
今天早上在写订单相关的代码
OrderInfo orderInfo = getByOrderNo(payProcessor.getOrderNo());
if (ObjectUtil.isNull(orderInfo)) {
throw new BusinessException(CourseErrorCode.ORDER_NOT_EXIST);
}
if (orderInfo.getDelFlag().equals(DelFlagEnum.YES.getValue())) {
throw new BusinessException(OrderErrorCode.TRANSFER_ORDER_INVALIDATE);
}
if (orderInfo.getStatus().equals(DelFlagEnum.YES.getValue())) {
throw new BusinessException(OrderErrorCode.SIGNUP_CANCEL);
}
if (orderInfo.getPurchaseStatus().equals(PayResultEnum.SUCCESS.getValue())) {
throw new BusinessException(OrderErrorCode.PURCHASE_ID_ALREADY_PAY_SUCC);
}
不得不说,这个代码看着好看,但是写起来是真的有点恶心,if throw , if throw , if throw
google 封装的 Preconditions 判断就相比优化了很多,但是 google 抛错都是公共的错误,比如 IllegalArgumentException , IllegalStateException 这些错误我们系统的公共错误拦截很可能不是希望获取到的,我们自己的系统更多是 像上面代码中的 BusinessException
代码
/**
* 在一个方法的开始,通常是大量的参数验证,很可能连续四五个 if(condition){throw new Business....},
* <p>
* 类似于 google 的 Preconditions.checkArgument(orgId != null, "orgId is null");,但是 google throw IllegalArgumentException ,我们一般使用 throw Business...
*
* @author lijian
* @date 2019/9/11 上午10:46
*/
@Slf4j
public class ErrorCodeUtils {
/**
* 如果 illegal 为 true 则会抛错 errorCode
*
* @param illegal
* @param errorCode
*/
public static void illegal(Boolean illegal, UniverseErrorCode errorCode) {
illegal(illegal, errorCode, null);
}
/**
* 如果 illegal 为 true 则会抛错 errorCode ,msg 为 errorCode
* 简化
* <pre> {@code
* if (campusId == null ) {
* throw new BusinessException(BaseErrorCode.PARAM_ERROR,"校区ID为空");
* }}</pre>
* 为
* <pre> {@code
* ErrorCodeUtils.illegal(campusId == null, BaseErrorCode.PARAM_ERROR,"校区ID为空");
* }</pre>
*
* @param illegal
* @param errorCode
* @param errorCode
*/
public static void illegal(Boolean illegal, UniverseErrorCode errorCode, String extMsg) {
if (illegal != null && illegal && errorCode != null) {
log.error("illegal illegal {},errorCode {},extMsg {}", illegal, errorCode, extMsg);
throw new BusinessException(errorCode, extMsg);
}
}
}
拓展
我们看一下现在的调用 ,由最开始的几行代码优化为一行代码
ErrorCodeUtils.illegal(campusId == null, BaseErrorCode.PARAM_ERROR,"校区ID为空");
在上面的这个调用中,同样有很多是重复代码,我们再次尝试消除这些,我们先看一下我们的错误枚举(简单举例,实际的错误枚举继承,内部枚举等相对复杂但是对本例无用)
public enum OrderErrorCode {
ORDER_PAY_DOING(6007, "订单支付处理中,请刷新后重试");
private int code;
private String message;
}
我们现在如果想要验证这个枚举,使用代码
ErrorCodeUtils.illegal(isDoing!=null && isDoing, OrderErrorCode.ORDER_PAY_DOING,"订单号为xxx 的订单正在处理中");
将 OrderErrorCode 继续优化
public enum OrderErrorCode {
ORDER_PAY_DOING(6007, "订单支付处理中,请刷新后重试");
private int code;
private String message;
public void illegal(Boolean illegal,String extMsg){
if(illegal!=null && illegal){
throw new BusinessException(this,extMsg);
}
}
}
我们现在再次想要验证这个枚举,使用代码
OrderErrorCode.ORDER_PAY_DOING.illegal(isDoing!=null && isDoing,"订单号为xxx 的订单正在处理中");
现在我们使用这个代码,代码不仅仅成为了一行,而且相对上面的再次精简
再优化
我们可能有这种需求,
if(condition){
log.info("this is error and params is {}",params);
throw new .....;
}
新建回调函数
/**
* @author lijian
* @date 2019/10/22 下午5:52
*/
@FunctionalInterface
public interface ErrorCallBack {
/**
* call when error
*/
void error();
}
添加处理方法
@Slf4j
public class ErrorCodeUtils {
public static void illegal(Boolean illegal, UniverseErrorCode errorCode) {
illegal(illegal, errorCode, "");
}
public static void illegal(Boolean illegal, UniverseErrorCode errorCode, String extMsg) {
illegal(illegal, errorCode, extMsg, null);
}
public static void illegal(Boolean illegal, UniverseErrorCode errorCode, String extMsg, ErrorCallBack callBack) {
if (illegal != null && illegal && errorCode != null) {
log.error("illegal illegal {},errorCode {},extMsg {}", illegal, errorCode, extMsg);
if (Objects.nonNull(callBack)) {
callBack.error();
}
throw new BusinessException(errorCode, extMsg);
}
}
public static void illegal(Boolean illegal, UniverseErrorCode errorCode, ErrorCallBack callBack) {
illegal(illegal, errorCode, null, callBack);
}
}
现在的调用方法
ErrorCodeUtils.illegal(isDoing!=null && isDoing,OrderErrorCode.ORDER_PAY_DOING,"订单正在处理中",()->log.warn("order is processoring ... orderNo {}",orderNo));