编写步骤:
1. 定义一个通用的业务接口
public interface SingleOperation<R> { RestResponse<R> doOperation(); }
2. 在Service实现类中定义一个复杂业务处理包装子类比如:创建付款单业务【CreatePayment】去实现SingleOperation接口
/** * 创建付款单业务 */ private class CreatePayment implements SingleOperation<String> { final org.slf4j.Logger log = CREATE_LOG; final FundPaymentCreateRequest request; FundPayment newPayment; private CreatePayment(final FundPaymentCreateRequest request) { this.request = request; } @Override public RestResponse<String> doOperation() { // 1. 检查必要参数 // 2. 没有单号则生成单号(调用方要保证不要重复请求) // 3. 插数据 // 4. 发消息 // 1. 检查基本参数 final ParamValidationResult checkResult = checkCreateParam(request); if (!checkResult.isPass()) { return checkResult.toRestResponse(); } // 2 若没有单号,生成一个单号 final String paymentNo; final boolean paymentNoExists; { final String existsPaymentNo = request.getPaymentNo(); if (!StringUtils.isEmpty(existsPaymentNo)) { // 外面传了单号进来,直接使用,并且需要校验此单号对应的付款单是否存在 paymentNo = existsPaymentNo; paymentNoExists = true; } else { // 没有单号,生成一个,并且后面不需要验证了 paymentNo = ascIdGenerator.generateString(FUND_PAYMENT); paymentNoExists = false; } } // 决定一下初始的 paymentStatus 是啥 ,传了则以传的为准,不传则默认 final EnumFundPaymentStatus paymentStatus = Optional.ofNullable(request.getPaymentStatus()).orElse(EnumFundPaymentStatus.TO_AUDIT); // 决定线上线下类型,传了以传的为准,不传则 receiverAccount 为空线下,不为空线上 final EnumFundPaymentType paymentType = Optional.ofNullable(request.getPaymentType()).orElseGet(() -> { if (StringUtils.isEmpty(request.getReceiverAccount())) { return EnumFundPaymentType.OFFLINE; } else { return EnumFundPaymentType.ONLINE; } }); // 3. 准备插入数据 return transactionTemplate.execute(status -> { // 如果单号是传进来的,先校验一遍是否存在 if (paymentNoExists) { final FundPayment queryEntity = new FundPayment(); queryEntity.setPaymentNo(paymentNo); final Integer count = fundPaymentMapper.selectCount(new QueryWrapper<>(queryEntity)); if (count > 0) { log.warn("创建付款单失败,付款单号 [{}] 重复。请求:[{}]", paymentNo, request); return fail(EnumCommonRestResponseCode.BusinessError, "付款单号重复,不能创建"); } } // 可以新增了 newPayment = new FundPayment(); newPayment.setPaymentNo(paymentNo); newPayment.setAmount(request.getAmount()); newPayment.setPaymentStatus(paymentStatus); newPayment.setPaymentType(paymentType); newPayment.setPayAccount(request.getPayAccount()); newPayment.setPayName(request.getPayName()); newPayment.setReceiverAccount(request.getReceiverAccount()); newPayment.setReceiverName(request.getReceiverName()); newPayment.setRemark(request.getRemark()); fundPaymentMapper.insert(newPayment); // 新增关系 final List<FundPaymentRelation> entities = request.getRelationList().stream().map(v -> { final FundPaymentRelation entity = new FundPaymentRelation(); entity.setPaymentNo(paymentNo); entity.setRelationType(v.getRelationType()); entity.setRelationNo(v.getRelationNo()); entity.fillInsert(); return entity; }).collect(Collectors.toList()); if (entities != null && entities.size() > 0) { fundPaymentRelationMapper.batchInsert(entities); } // 发消息 sendMq(); return success(paymentNo); }); }
这样我们把一个复杂的业务拆分成多个子类,去写各自的逻辑,就可以把复杂问题简单化,而不是我们通过抽取方法,方法之间互相调用,这样业务复杂了,代码很难读懂。